Tkinter借助Canvas在两个独立窗口分别加载图片时提示pyimage2不存在错误
报错核心原因
- 违反Tkinter的单根窗口规则:同一进程内仅允许存在1个通过
Tk()初始化的主根窗口。在两个窗口类的初始化方法里分别创建Tk()实例时,第二个实例启动后,后续加载的PhotoImage会因为Tcl解释器绑定异常,触发image 'pyimage2' doesn't exist的引用错误。 - 图片对象被垃圾回收:
PhotoImage属于弱引用对象,如果将其存为类方法里的临时局部变量,初始化流程结束后该变量就会被Python垃圾回收销毁,Canvas绑定的图片引用会直接失效。 - 图片路径不匹配:代码中配置的图片路径与本地实际存储的文件路径不一致,即便解决前面两个问题,也会触发图片文件加载失败的错误。
可正常运行的实现方式
实现逻辑遵循三个核心要求:
- 全流程仅创建1个全局
Tk()根实例,第二个独立窗口用Toplevel组件实现,不再重复实例化Tk() - 将
PhotoImage对象绑定为类的实例属性,避免被垃圾回收 - 校验图片路径,与本地文件实际存储位置对齐
from tkinter import Tk, Canvas, PhotoImage, Toplevel PANEL_HEIGHT = 440 PANEL_WIDTH = 304 # 替换为与本地路径匹配的图片地址 BKG_IMG = "./backgrounds/wireframe_welcome.png" MANAGE_ACC_BKG_IMG = "./backgrounds/manage_acc_ui_bkg.png" # 创建全局唯一的Tk根实例 root = Tk() # 隐藏默认的主根窗口,仅展示自定义的两个独立窗口 root.withdraw() class window1: def __init__(self): # 用Toplevel创建独立框架,替代原有的Tk()实例 self.panel = Toplevel(root) self.panel.geometry(f"{PANEL_WIDTH}x{PANEL_HEIGHT}") self.canvas = Canvas(self.panel, width=2*PANEL_WIDTH, height=2*PANEL_HEIGHT) # 图片挂到实例属性上,避免被垃圾回收 self.img = PhotoImage(file=BKG_IMG) self.canvas.create_image(PANEL_WIDTH, PANEL_HEIGHT, image=self.img) self.canvas.place(x=-(PANEL_WIDTH/2), y=-(PANEL_HEIGHT/2)) class window2: def __init__(self): self.panel = Toplevel(root) self.panel.geometry(f"{PANEL_WIDTH}x{PANEL_HEIGHT}") self.canvas = Canvas(self.panel, width=2*PANEL_WIDTH, height=2*PANEL_HEIGHT) self.img = PhotoImage(file=MANAGE_ACC_BKG_IMG) self.canvas.create_image(PANEL_WIDTH, PANEL_HEIGHT, image=self.img) self.canvas.place(x=-(PANEL_WIDTH / 2), y=-(PANEL_HEIGHT / 2)) window1() window2() # 启动全局主事件循环 root.mainloop()
注意:所有通过
Toplevel创建的独立窗口都会自动接入全局主事件循环,不需要单独启动循环,也不会再出现图片引用丢失的问题。
内容的提问来源于stack exchange,提问作者gyan mishra
相关产品推荐
相关产品推荐

