这是我在python (Tkinter模块)中遇到的最奇怪的事情,有什么帮助理解它吗?



所以基本上我有一个叫做click_roll的函数,如果你点击滚动按钮,它会滚动骰子并将结果显示为骰子一侧的图像,出于某种原因,程序只会工作,如果函数在结束时出现错误!这怎么说得通呢?(函数末尾的error_variable不存在,所以给它加1会导致错误)

from tkinter import *
import random
from PIL import ImageTk,Image
root = Tk()
root.geometry('300x400')
def rolldice():
number = random.randint(1,6)
return number
def click_roll():
number = rolldice()
if number == 2:
image1 = ImageTk.PhotoImage(Image.open("dice2.jpg"))
image1_label = Label(image=image1)
image1_label.place(relx=0.5, rely=0.3, anchor=CENTER)
elif number == 3:
image1 = ImageTk.PhotoImage(Image.open("dice3.jpg"))
image1_label = Label(image=image1)
image1_label.place(relx=0.5, rely=0.3, anchor=CENTER)
elif number == 4:
image1 = ImageTk.PhotoImage(Image.open("dice4.jpg"))
image1_label = Label(image=image1)
image1_label.place(relx=0.5, rely=0.3, anchor=CENTER)
elif number == 5:
image1 = ImageTk.PhotoImage(Image.open("dice5.jpg"))
image1_label = Label(image=image1)
image1_label.place(relx=0.5, rely=0.3, anchor=CENTER)
elif number == 6:
image1 = ImageTk.PhotoImage(Image.open("dice6.jpg"))
image1_label = Label(image=image1)
image1_label.place(relx=0.5, rely=0.3, anchor=CENTER)
elif number == 1:
image1 = ImageTk.PhotoImage(Image.open("dice1.jpg"))
image1_label = Label(image=image1)
image1_label.place(relx=0.5, rely=0.3, anchor=CENTER)

error_variable +=1

image1 = ImageTk.PhotoImage(Image.open("dice1.jpg"))
image1_label = Label(image=image1)
roll_button = Button(root,text='Roll',height=5,width=12,command=click_roll)
roll_button.grid(row=0,column=1)
image1_label.place(relx=0.5, rely=0.3, anchor=CENTER)
roll_button.place(relx=0.5, rely=0.5, anchor=CENTER)
root.mainloop()

ImageTk.PhotoImage有一个__del__的实现,从tkinter中删除图像(不确定这里究竟发生了什么,因为我没有使用tkinter)。

您的click_roll创建了一个图像并删除了对它的所有引用(由于某种原因,标签没有保留对图像的引用)。最后,调用图像上的__del__方法,并将其从主窗口中删除。

当你在click_roll函数中引发一个异常时,回溯将使帧保持活动状态,因此图像不会从主窗口中删除。

为了防止这种情况的发生,你应该重新构造你的代码,使图像存储在一个"安全"位置。

# store the images in a variable that "survives" the click_roll handler
die_images = {
1: ImageTk.PhotoImage('dice1.jpg'),
...
6: ImageTk.PhotoImage('dice6.jpg')
}

def click_roll():
number = rolldice()
image = die_images[number]  # pick the correct image
label = Label(image=image)
...

如果您熟悉字典推导式,您还可以简化die_images的创建:

die_images = {number: ImageTk.PhotoImage(f'dice{number}.jpg') for number in range(1, 7)}

最后的想法:这看起来非常奇怪,如果这是预期的行为,也许一个tkinter专家可以评论。在我看来,标签应该保留对图像的参考。但也许tkinter和Pillow之间的交互不是最优的。

图片消失了,因为在函数终止后,带有图像的新标签被垃圾收集器吃掉了。您不需要创建新标签,只需要替换标签上的图像并创建指向该图像的附加链接,并考虑到Sembei Norimaki的评论,click_roll()函数代码:

def click_roll():
number = rolldice()
image1 = ImageTk.PhotoImage(Image.open(f'heart{number}.png'))
image1_label.configure(image=image1)
image1_label.image = image1

相关内容

  • 没有找到相关文章

最新更新