How to create multiple images in tkinter that can scale

Question:

I am creating a 3D rendering system in Tkinter and adding in textured walls. However, when I want to create another image the original disappears, and It will only render 1 wall and it appears that there can only be one wall.

Code:

import getkey
import threading
import PIL
from PIL import Image, ImageTk
from tkinter import *

global key
key = ""
x_cord = 0
y_cord = 0

def input_check(): #gets keyboard input
  global key
  while True:
    unprocessed_key = str(getkey.getkey())
    if len(key) > 0:
      key = key + unprocessed_key
    else:
      key = unprocessed_key

window = Tk()
window.title(" ")
photo = PIL.Image.open("wall.png")
logoImg = ImageTk.PhotoImage(photo)
window.iconphoto(False, logoImg)
window.state("normal")
geo_draw = Canvas(window, width=400, height=400, background="#000000") #creats the geomatry drawer

input_thread = threading.Thread(target=input_check, args=()) #allows keyboard input
input_thread.start()

geo_draw.pack(fill=BOTH, expand=1)

render_list = [[0,1,"#0000FF",1],[0,1,"wall",0]] #if you add ,[1,1,"wall",0] to the render list so that it creates another the first will disapear
winX = 0
winY = 0
while True:
  geo_draw.delete("all")
  geo_draw.configure(scrollregion=(-(winX//2), -(winY//2), (winX//2), (winY//2)))
  geo_draw.xview_moveto(1)
  geo_draw.yview_moveto(1)
  for x in range(len(render_list)):
    y_render_cord = render_list[x][1] - y_cord
    if render_list[x][3] == 0: #draws a image for the front face of the wall
      xdiv = (x_cord + render_list[x][0] + 0.481) *-250 / y_render_cord
      ydivB = round(240 / y_render_cord)
      front_render_image = PIL.Image.open(f"{render_list[x][2]}.png")
      try:
        realImg = front_render_image.resize((ydivB, ydivB), PIL.Image.Dither.NONE) #scales the image
      except:
         realImg = front_render_image.resize([200,200]) #stops the image rendering to large
      realImg = ImageTk.PhotoImage(realImg)
      geo_draw.create_image(xdiv, 0, image = realImg, anchor = CENTER) #draws the image
    else: #draws the side of the walls
      wall_cord = (x_cord + render_list[x][0]) *-250
      ydiv = 120 / (y_render_cord+render_list[x][3])
      ydivB = round(120 / y_render_cord)
      xdiv = wall_cord / y_render_cord
      xdivB = wall_cord / (y_render_cord + render_list[x][3])
      geo_draw.create_polygon([xdiv, ydivB, xdivB, ydiv, xdivB, -ydiv, xdiv, -ydivB], fill=render_list[x][2])
  for letter in key: # gets keyboard input
    if letter == "w":
      y_cord += 0.1
    elif letter == "a":
      x_cord -= 0.1
    elif letter == "s":
      y_cord -= 0.1
    elif letter == "d":
      x_cord += 0.1
  key = ""
  window.update()
  window.update_idletasks()
  winX = geo_draw.winfo_width()
  winY = geo_draw.winfo_height()

You will need to make a texture called "wall.png", but it can be any image.

Thanks

Asked By: Bozo United

||

Answers:

I have experienced a similar situation when I was doing my project. You are rewriting the realImg every single time it loops. It is a problem because as soon as you create a new image in that SAME variable then the old one is gone. So you have to make sure it’s still present like a memory because ImageTk will not create a memory of its own. So you have to append that variable to a list so that it is stored.

So do something like this:

image_storing = []

LATER: image_storing.append(realImg)

Hopefully this works for you.

Answered By: ss3387
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.