From what I've read, ImageTk
should convert a Pillow image into a format that Tkinter can display. (Indeed, when I don't, Tkinter fails with an error.) However, when I run this program on my Windows computer, the Tkinter box says it's not responding and does not display the images.
from PIL import Image, ImageDraw
class Block:
def __init__(self, x=30, y=10, speed=None, size=2.5):
self.x = x
self.y = y
self.size = size # radius
if speed is None:
speed = self.size * 2
self.speed = speed
def draw(self, image):
width, height = image.size
drawer = ImageDraw.Draw(image)
drawer.rectangle(((self.x - self.size, height - (self.y - self.size)), (self.x + self.size, height - (self.y + self.size))), fill="white")
class BallDodge():
def __init__(self):
self.width = 400
self.height = 300
self.main_player = Block(self.width // 2)
self.balls = []
self.frame = 0
self.frames_between_balls = 20
self.frames_since_last_ball = self.frames_between_balls
self.input_function = self.get_human_input
self.states = []
@property
def state(self):
ans = Image.new('RGBA', (self.width, self.height), "black")
self.main_player.draw(ans)
return ans
def get_human_input(self, *args, **kwargs):
try:
ans = int(input("1, 2, 3, or 4:"))
if ans > 4:
raise ValueError("Can't be greater than 4")
elif ans < 1:
raise ValueError("Can't be less than 1")
if ans == 1:
return [1, 0]
elif ans == 2:
return [0, 0]
elif ans == 3:
return [0, 1]
elif ans == 4:
return [1, 1]
else:
raise ValueError("Somehow it's not one of the specified numbers. You are magical.")
except Exception as e:
print("Invalid input")
print(e)
return self.get_human_input()
def step(self):
inpt = self.input_function(self.state)
directions = [-1, 1]
for i in range(2):
self.main_player.x += directions[i] * inpt[i]
self.states.append(self.state)
if __name__ == "__main__":
game = BallDodge()
import tkinter as tk
from PIL import ImageTk, Image
root = tk.Tk()
my_image = ImageTk.PhotoImage(game.state)
game.state.show()
while True:
panel = tk.Label(image = ImageTk.PhotoImage(game.state), master = root)
panel.pack()
# panel = Label(root, image = ImageTk.PhotoImage(game.state))
# panel.pack(side = "bottom", fill = "both", expand = "yes")
root.update_idletasks()
root.update()
game.step()
Things I've noticed:
If I do game.state.show()
it will open up the image just fine, so there's definitely an image there.
If I do hit one of the number keys to advance to the next frame, the Tkinter window gets twice as tall, but still displays nothing.
How can I get a loop such that I can display a Pillow image in a Tkinter window, get user input, and then display a new image?