如何在多个Customtkinter窗口中复用同一张图片?
问题:Customtkinter多窗口图片显示报错:
image "pyimage2" doesn't exist 问题背景
使用Customtkinter构建GUI,主窗口中通过PIL库在CTkLabel里正常显示同目录下的logo图片,但在设置窗口中执行相同逻辑时触发错误。
主窗口可运行代码
class MainWindow(ctk.CTk): def __init__(self): super().__init__() self.geometry("700x400") self.img_frame = ctk.CTkFrame(self) self.img_frame.pack(pady=10, padx=10, fill='x') self.logo = ctk.CTkImage(light_image=Image.open("./logo.png"), size=(250, 80)) print(self.logo) self.img_label = ctk.CTkLabel(self.img_frame, image= self.logo, compound="left", text="") self.img_label.grid(pady=10, padx=10, column=0, row=0, sticky="w")
设置窗口尝试代码
class SetupWindow(ctk.CTk): def __init__(self, parent): super().__init__() self.parent = parent self.geometry("700x370") self.title_frame = ctk.CTkFrame(self, height=100, width=680) self.title_frame.grid(row=0, column=0, padx=10, pady=10, sticky='news') self.logo = ctk.CTkImage(light_image=Image.open("./logo.png"), size=(250, 80)) print(self.logo) self.img = ctk.CTkLabel(self.title_frame, image= self.logo, compound="left", text="") self.img.grid(pady=10, padx=10, column=0, row=0, sticky="w")
报错信息
Exception in Tkinter callback Traceback (most recent call last): in __init__ self.img = ctk.CTkLabel(self.title_frame, image= self.logo, compound="left", text="") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in _configure self.tk.call(_flatten((self._w, cmd)) + self._options(cnf)) _tkinter.TclError: image "pyimage2" doesn't exist
解决方案
这个错误的核心原因是:Tkinter不允许在多个独立的CTk(即Tk根窗口)实例间共享图片资源。每个CTk实例对应一个独立的Tcl解释器上下文,图片资源绑定在创建它的上下文里,无法跨上下文访问。
推荐方案:将设置窗口改为CTkToplevel子窗口
把设置窗口的继承类从ctk.CTk改为ctk.CTkToplevel,并在初始化时传入主窗口作为父组件,这样设置窗口会共享主窗口的Tcl上下文,图片资源可以正常加载:
class SetupWindow(ctk.CTkToplevel): def __init__(self, parent): super().__init__(parent) # 传入父窗口作为参数 self.parent = parent self.geometry("700x370") self.title_frame = ctk.CTkFrame(self, height=100, width=680) self.title_frame.grid(row=0, column=0, padx=10, pady=10, sticky='news') self.logo = ctk.CTkImage(light_image=Image.open("./logo.png"), size=(250, 80)) print(self.logo) self.img = ctk.CTkLabel(self.title_frame, image=self.logo, compound="left", text="") self.img.grid(pady=10, padx=10, column=0, row=0, sticky="w")
备选方案(不推荐):强制隔离上下文
如果必须使用独立的CTk窗口,需要在创建第二个窗口前重置Tkinter的图片ID,或者确保每个窗口的图片资源完全独立加载并绑定到自身上下文。但这种方法容易引发其他Tkinter上下文冲突,不建议使用。
内容的提问来源于stack exchange,提问作者afonso granja
相关产品推荐
相关产品推荐

