所以基本上我有一个叫做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