【发布时间】:2018-06-21 01:02:42
【问题描述】:
根据我的阅读,ImageTk 应该将 Pillow 图像转换为 Tkinter 可以显示的格式。 (实际上,如果我不这样做,Tkinter 会失败并出现错误。)但是,当我在 Windows 计算机上运行此程序时,Tkinter 框说它没有响应并且不显示图像。
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()
我注意到的事情:
如果我这样做game.state.show(),它会很好地打开图像,所以那里肯定有图像。
如果我确实按了其中一个数字键以前进到下一帧,Tkinter 窗口的高度会增加一倍,但仍不显示任何内容。
如何获得一个循环,以便在 Tkinter 窗口中显示 Pillow 图像,获取用户输入,然后显示新图像?
【问题讨论】:
-
窗口变得越来越高,因为你把
packing_new_tk.Labels放在里面。您已经知道如何动态地将 Pillow 图像导入 tkinter——即使用ImageTk.PhotoImage()。您不知道的是如何显示它们,然后再更新它们。要更改标签上使用的图像,您可以使用类似于panel.config(image=new_imagetk)的内容。 -
但是 Tkinter 窗口甚至没有显示我放入的第一张图片。很高兴了解更改图像的配置功能,但即使我将面板线移到循环之外,我的 Tkinter 窗口也只是空白。 (这让我觉得我真的不知道如何将 Pillow 图像导入 tkinter,更不用说动态了。)
-
另一个大问题是您没有正确编程
tkinter。像您的while True:循环这样的东西不是它们是如何工作的。简而言之,您需要始终在某个地方调用.mainloop()以使您的应用程序运行。从那时起,一切都必须发生在该循环内。基本上你想要做的是动画,所以这就是你需要了解如何做的(在stackoverflow上有很多与此相关的问题)。这通常使用带有通用小部件方法after()的回调函数来完成。 -
我担心我的所有逻辑都包含在 tkinter 函数中,因为我只想使用 tkinter 来显示游戏,而不是运行它。我看到了如何重构它,所以它确实使用主循环而不将游戏耦合到 tkinter。谢谢您的反馈!我正在使用的循环来自this question,它似乎暂时对我有用,所以这就是我现在要使用的。
标签: python image loops tkinter pillow