Tkinter多窗口显示选中图片报错:_tkinter.TclError
问题分析与解决方案
错误根源
报错_tkinter.TclError: image "portrait_5" doesn't exist的核心原因:
- 配置阶段保存的是自定义字符串(如
portrait_5),这些字符串既不是Tkinter注册的图像对象名称,也未与实际图片文件建立对应关系。 - 在
lancer函数中直接将配置文件里的字符串传给Label的image参数,Tkinter无法识别该字符串对应的图像资源。 - 该问题与计时功能的
after函数无关,完全是图像资源的加载与引用逻辑错误。
修复步骤
1. 建立字符串到图片文件的映射
修正liste_portrait_photo,让它直接对应实际的图片文件名:
# 替换原liste_portrait_photo,与实际图片文件名一一对应 liste_portrait_photo = [ "portrait_satanas.png", "portrait_folle.png", "portrait_sorciere.png", "portrait_vieux.png" ]
2. 在lancer函数中加载对应图片并保留引用
在lancer函数里,根据配置文件保存的图片文件名动态加载图像,同时将图像对象绑定到Label的属性上,防止Python垃圾回收机制回收图像资源:
# 替换lancer函数中PILOTE 1部分的头像代码 # 加载对应图片 portrait_path = f"images/{data['Portrait pilote 1']}" pilote1_img = ImageTk.PhotoImage(Image.open(portrait_path)) # 创建Label并绑定图像引用 portrait_pilote_1 = Label(frame1, image=pilote1_img, compound="top", border="0") portrait_pilote_1.image = pilote1_img # 保留引用,避免GC回收 portrait_pilote_1.place(relx=0.5, y=120, anchor="center")
3. 同理修复PILOTE 2的图片显示
# 在PILOTE 2部分添加头像加载代码 portrait_path_p2 = f"images/{data['Portrait pilote 2']}" pilote2_img = ImageTk.PhotoImage(Image.open(portrait_path_p2)) portrait_pilote_2 = Label(frame2, image=pilote2_img, compound="top", border="0") portrait_pilote_2.image = pilote2_img portrait_pilote_2.place(relx=0.5, y=120, anchor="center")
4. 优化窗口切换逻辑(可选)
原代码中销毁主窗口后创建新Tk()实例的方式不规范,建议改用Toplevel子窗口并隐藏主窗口:
# 替换lancer函数开头的窗口代码 # fenetre_ppale.destroy() # 注释销毁主窗口的代码 fenetre_ppale.withdraw() # 隐藏主窗口 fenetre_ppale2 = Toplevel(fenetre_ppale) # 创建子窗口
完整修改后的关键代码片段
# 全局变量部分修正 liste_portrait_photo = [ "portrait_satanas.png", "portrait_folle.png", "portrait_sorciere.png", "portrait_vieux.png" ] # lancer函数中图片加载部分 def lancer(): global frame3, frame4, frame1, fenetre_ppale2 fenetre_ppale.withdraw() # 隐藏主窗口而非销毁 fenetre_ppale2 = Toplevel(fenetre_ppale) fenetre_ppale2.geometry("1720x1080+10+10") # ... 其他代码保持不变 ... # 读取配置数据 with open('configcourse.json', 'r') as fic: data = json.load(fic) # PILOTE 1区域 frame1 = Frame(fenetre_ppale2, width=573, height=800, bg="brown", pady=10, padx=10) frame1.place(x=191, y=121) lbl_frame1 = Label(frame1, text=data['Pilote 1'], font="Futura 42 bold", padx=20, bg="brown", fg="white") lbl_frame1.place(relx=0.5, y=50, anchor="center") # 加载并显示PILOTE1头像 portrait_path = f"images/{data['Portrait pilote 1']}" pilote1_img = ImageTk.PhotoImage(Image.open(portrait_path)) portrait_pilote_1 = Label(frame1, image=pilote1_img, compound="top", border="0") portrait_pilote_1.image = pilote1_img portrait_pilote_1.place(relx=0.5, y=120, anchor="center") # PILOTE 2区域 frame2 = Frame(fenetre_ppale2, width=573, height=800, bg="navy", pady=10, padx=10) frame2.place(x=955, y=121) lbl_frame2 = Label(frame2, text=data['Pilote 2'], font="Futura 42 bold", padx=20, bg="navy", fg="white") lbl_frame2.place(relx=0.5, y=50, anchor="center") # 加载并显示PILOTE2头像 portrait_path_p2 = f"images/{data['Portrait pilote 2']}" pilote2_img = ImageTk.PhotoImage(Image.open(portrait_path_p2)) portrait_pilote_2 = Label(frame2, image=pilote2_img, compound="top", border="0") portrait_pilote_2.image = pilote2_img portrait_pilote_2.place(relx=0.5, y=120, anchor="center") fenetre_ppale2.mainloop()
内容的提问来源于stack exchange,提问作者Lokazionel
相关产品推荐
相关产品推荐

