You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter报错:image 'pyimage18'不存在,寻求解决方案

Tkinter应用_tkinter.TclError: image "pyimage18" doesn't exist问题排查与解决

问题描述

基于Tkinter开发的InteL-Trader桌面应用此前运行完全正常,突然触发_tkinter.TclError: image "pyimage18" doesn't exist错误,错误发生在StartPage类加载logo图片到Logo_screen_frame的环节,尝试过网上常见解决方案后问题仍未解决。

相关代码

# 定义应用主框架类,仅包含菜单,所有页面都加载在此框架上
class SeaofBTCapp(Tk):

    def __init__(self, *args, **kwargs):
        Tk.__init__(self, *args, **kwargs)
       
        # 设置应用图标(需为.ico格式)
        Tk.iconbitmap(self, default='C:/Users/aurel/Desktop/image.ico')

        # 设置窗口标题
        Tk.wm_title(self, 'InteL-Trader')
        self.state("zoomed") # 窗口默认最大化

        global screen_height
        global screen_width
        global one_part
        global two_part

        screen_width=self.winfo_screenwidth()
        screen_height=self.winfo_screenheight()

        # 屏幕宽度百分比单位
        one_part=(16.36/100*screen_width)
    
        # 屏幕高度百分比单位
        two_part=10/100*screen_height
       
        # 应用整体容器框架,位于根窗口之上
        Whole_App_Frame=Frame(self, width=screen_width, height=screen_height, bg='gold')
        Whole_App_Frame.grid(row=0, column=0, columnspan=3)

        ################################################
            # 菜单部分
        ################################################
        # 在应用容器框架上创建菜单容器
        my_menu=Menu(Whole_App_Frame)

        # 将菜单设置为应用的主菜单
        self.config(menu=my_menu)
        
        def Stop_bot(): # 触发云端代码停止的函数
            pass

        file_menu=Menu(my_menu)
        my_menu.add_cascade(label="Home", menu=file_menu)
        file_menu.add_command(label="Home Page", command=lambda: controller.show_frame(StartPage))
        file_menu.add_separator()
        file_menu.add_command(label="Log out MT5 Account", command=Stop_bot)
        file_menu.add_separator()
        file_menu.add_command(label="Exit", command=Whole_App_Frame.quit)
        
        # 创建Account菜单选项
        Account_menu=Menu(my_menu)
        my_menu.add_cascade(label="Account", menu=Account_menu)
        Account_menu.add_command(label="Account Data Page", command=lambda: controller.show_frame(AccountPage))
        Account_menu.add_separator()
        Account_menu.add_command(label="Receipts|Reports|Statements Downloads", command=lambda: controller.show_frame(DownloadsPage))

        # 创建Training菜单选项
        Training_menu=Menu(my_menu)
        my_menu.add_cascade(label="Training", menu=Training_menu)
        Training_menu.add_command(label="How to use Intel Trader", command=lambda: controller.show_frame(HowtoIntel))
        Training_menu.add_separator()
        Training_menu.add_command(label="Forex basics", command=lambda: controller.show_frame(ForexBasics))
        Training_menu.add_separator()
        Training_menu.add_command(label="Advanced Forex analysis and Strategies", command=lambda: controller.show_frame(AdvancedForex))

        # 创建Help菜单选项
        help_menu=Menu(my_menu)
        my_menu.add_cascade(label="Help Centre", menu=help_menu)
        help_menu.add_command(label="Self Help Centre", command=lambda: controller.show_frame(CommunityHelpPage))
        help_menu.add_separator()
        help_menu.add_command(label="Contact US", command=lambda: controller.show_frame(ContactsPage))
        help_menu.add_separator()
        help_menu.add_command(label="Direct Message and Calls", command=lambda: controller.show_frame(CallPage))

        # 创建Terms and Conditions菜单选项(无下拉)
        my_menu.add_command(label="Terms and Conditions", command=lambda: controller.show_frame(TermsPage))

        self.frames={} 
        # 注:此处省略了部分页面类,如DownloadsPage等
        for F in (StartPage, AccountPage):    # 加载所有页面框架,可通过按钮调用切换
            frame=F(Whole_App_Frame, self)
            self.frames[F]=frame
            frame.grid(row=0, column=0, sticky='nswe')
        
        self.show_frame(StartPage) # 默认加载StartPage作为首页
        
    def show_frame(self, cont):  # 切换页面的函数,将指定页面置于顶层
        frame=self.frames[cont]
        frame.tkraise()

# 定义StartPage页面类
class StartPage(Frame):
    def __init__(self, parentclass, controller):
        
        Frame.__init__(self, parentclass)

        # 创建第一列框架,使用屏幕宽高的百分比设置尺寸
        # Logo和应用名称框架
        Logo_screen_frame=LabelFrame(self, width=int(one_part), height=int(two_part), bg='green')
        Logo_screen_frame.grid(column=0, row=0, padx=2, pady=0, sticky='n', columnspan=2, rowspan=1)
        
        # 加载并显示logo图片
        logo=Image.open("C:/Users/aurel/trading app/logo1.PNG")
        logo=logo.resize((int(one_part/3), int(two_part-15)))
        ph=ImageTk.PhotoImage(logo)
        label=Label(Logo_screen_frame, image=ph)
        label.image=ph
        label.grid(row=0, column=0)
        ......

app=SeaofBTCapp()
app.geometry(str(screen_width)+'x'+str(screen_height))
ani=animation.FuncAnimation(f, animate, interval=1000)

app.mainloop()

报错信息

File "c:\Users\aurel\trading app\freshtutorial.py", line 793, in <module>
    app=SeaofBTCapp()
        ^^^^^^^^^^^^^
  File "c:\Users\aurel\trading app\freshtutorial.py", line 205, in __init__
    frame=F(Whole_App_Frame, self)
          ^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\aurel\trading app\freshtutorial.py", line 234, in __init__
    label=Label(Logo_screen_frame, image=ph)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python312\Lib\tkinter\__init__.py", line 3237, in __init__
    Widget.__init__(self, master, 'label', cnf, kw)
  File "C:\Python312\Lib\tkinter\__init__.py", line 2648, in __init__
    self.tk.call(
_tkinter.TclError: image "pyimage18" doesn't exist
PS C:\Users\aurel\trading app>        

针对性解决方案

1. 解决Tk根实例冲突

该错误最常见原因是多个Tk根窗口实例共存,你的代码中animation.FuncAnimation依赖的matplotlib默认会创建独立的Tk根实例,和你自定义的SeaofBTCapp(继承自Tk)冲突。

修改方式:初始化matplotlib时指定TkAgg后端,并绑定到已有的应用窗口:

import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

# 在创建FuncAnimation前,将图表绑定到应用窗口
canvas = FigureCanvasTkAgg(f, master=app)
canvas.draw()
canvas.get_tk_widget().pack(side='top', fill='both', expand=1)

ani=animation.FuncAnimation(f, animate, interval=1000)

2. 强化图片引用避免垃圾回收

虽然你已做label.image=ph保留引用,但如果页面框架被意外重建,仍可能丢失引用。将图片引用存储到更持久的控制器实例中:

# 在StartPage的__init__中修改
ph=ImageTk.PhotoImage(logo)
label=Label(Logo_screen_frame, image=ph)
# 将引用存储到应用控制器实例
controller.logo_photo = ph
label.image=ph

3. 规范图片路径写法

使用原始字符串或双反斜杠避免路径转义问题:

# 两种可选写法
logo=Image.open(r"C:\Users\aurel\trading app\logo1.PNG")
# 或
logo=Image.open("C:\\Users\\aurel\\trading app\\logo1.PNG")

4. 确保页面框架仅创建一次

避免重复创建页面框架导致图片实例冲突,修改创建逻辑:

self.frames={} 
for F in (StartPage, AccountPage):    
    if F not in self.frames:
        frame=F(Whole_App_Frame, self)
        self.frames[F]=frame
        frame.grid(row=0, column=0, sticky='nswe')

5. 清理进程缓存

VSCode的Python进程可能残留旧实例导致资源冲突,完全关闭VSCode后重新打开,或在终端杀死所有Python进程后再运行程序。

内容的提问来源于stack exchange,提问作者SUNNETDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 00:07:31