Tkinter点击按钮报错_tkinter.TclError: image "pyimage2"不存在如何解决
问题原因
这个报错是Tkinter的经典问题,根源是PhotoImage类型的图片对象被Python垃圾回收机制自动清理:
Tkinter内部不会额外持有PhotoImage对象的引用,哪怕你已经将图片赋值给按钮的image属性。如果图片对象没有被其他长生命周期的变量/对象持有,Python会在变量作用域失效后自动回收该图片对应的内存资源,后续Tkinter渲染控件时找不到对应的图片资源,就会抛出image "pyimageX" doesn't exist的错误。
你代码里的问题出在alphabet()函数内部:你创建的picAlphabetMaj是函数局部变量,函数执行结束后该变量的引用就会失效,你写的picAlphabetMaj.pictureAlphabetMaj = pictureAlphabetMaj是把原PIL图片绑定到了即将被回收的PhotoImage对象本身,根本起不到持有引用的作用。
修复方案
只需要把PhotoImage对象绑定到使用它的按钮组件的属性上即可,按钮被Canvas持有不会被回收,对应的图片引用也就会一直存在:
把alphabet()函数里的这行代码:
picAlphabetMaj.pictureAlphabetMaj = pictureAlphabetMaj
替换为:
boutonAlphabetMaj.img = picAlphabetMaj
修改后的完整alphabet()函数如下:
def alphabet() : canvas.delete("boutonAlphabet") # Bouton Alphabet Majuscule pathAlphabetMaj = os.path.join("test/alphabetMaj.png") pictureAlphabetMaj = Image.open(pathAlphabetMaj) picAlphabetMaj = ImageTk.PhotoImage(pictureAlphabetMaj) boutonAlphabetMaj = tk.Button(canvas, image=picAlphabetMaj, borderwidth=0, bg="#383838", activebackground="#4a4a4a", cursor="hand2") # 改动在这里:将图片对象绑定到按钮的属性上,避免被回收 boutonAlphabetMaj.img = picAlphabetMaj boutonAlphabetMaj.bind("<Enter>", lambda e: boutonAlphabetMaj.config(fg='#383838', bg='#3f3f3f')) boutonAlphabetMaj.bind("<Leave>", lambda e: boutonAlphabetMaj.config(fg='#3f3f3f', bg='#383838')) canvas.create_window(200, 500, window=boutonAlphabetMaj, tags=("boutonAlphabetMaj"))
补充注意
所有在局部作用域创建的Tkinter PhotoImage对象,都需要手动绑定到长生命周期对象(比如窗口、Canvas、控件本身)的属性上,或者存到全局的列表/字典中,否则都会触发该类报错。
内容的提问来源于stack exchange,提问作者Quast
相关产品推荐
相关产品推荐

