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

Python类中Canvas无法显示图片问题求助

修复Canvas中类创建图片不显示的问题

问题描述

尝试使用Python类在Canvas中创建图片,但运行代码后图片无法显示。在类外创建图片时代码可正常运行,相关代码如下:

import tkinter as tk
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from PIL import Image,ImageTk

# 原代码缺少root对象初始化,需补充类似 root = ttk.Window() 的代码
CompaniesFrame = ttk.LabelFrame(root, text =" Companies ")
CompaniesFrame.place(x=500, y=50)
CompaniesCanvas = ttk.Canvas(CompaniesFrame, width=900, height=500)
CompaniesCanvas.pack()


CompanyPhoto = "Company.png"
class CompanyIconClass:
    def __init__(self,CompanyName,ImagePath):
        self.CompanyName = CompanyName
        self.ImagePath = ImagePath

    def CreatImage(self):
        def OpenCompany(event):
            pass
        CompanyImage = ttk.PhotoImage(file = self.ImagePath)
        CompanyImage = CompanyImage.subsample(4)
        CompanyElement = CompaniesCanvas.create_image(150, 150, image=CompanyImage)
        CompaniesCanvas.tag_bind(CompanyElement, "<Button-1>", OpenCompany)


CompanyIconClass("Img1",CompanyPhoto).CreatImage()

问题原因

核心问题是PhotoImage对象被Python垃圾回收机制回收:CreatImage方法内的CompanyImage是局部变量,方法执行完成后,没有任何外部对象持有对它的引用,导致该对象被销毁,Canvas无法找到对应的图片资源。

修复方案

方案1:将图片对象绑定到类实例

把图片对象赋值给类实例的属性,让实例一直持有引用,避免被回收:

class CompanyIconClass:
    def __init__(self,CompanyName,ImagePath):
        self.CompanyName = CompanyName
        self.ImagePath = ImagePath

    def CreatImage(self):
        def OpenCompany(event):
            pass
        # 将图片对象绑定到self,保持引用
        self.CompanyImage = ttk.PhotoImage(file = self.ImagePath)
        self.CompanyImage = self.CompanyImage.subsample(4)
        CompanyElement = CompaniesCanvas.create_image(150, 150, image=self.CompanyImage)
        CompaniesCanvas.tag_bind(CompanyElement, "<Button-1>", OpenCompany)

方案2:将图片对象存储到Canvas对象中

给Canvas添加一个存储图片的列表,把图片对象存入其中,保持引用:

class CompanyIconClass:
    def __init__(self,CompanyName,ImagePath):
        self.CompanyName = CompanyName
        self.ImagePath = ImagePath

    def CreatImage(self):
        def OpenCompany(event):
            pass
        CompanyImage = ttk.PhotoImage(file = self.ImagePath)
        CompanyImage = CompanyImage.subsample(4)
        # 初始化Canvas的图片存储列表(如果不存在)
        if not hasattr(CompaniesCanvas, "images"):
            CompaniesCanvas.images = []
        # 将图片加入列表,保持引用
        CompaniesCanvas.images.append(CompanyImage)
        CompanyElement = CompaniesCanvas.create_image(150, 150, image=CompanyImage)
        CompaniesCanvas.tag_bind(CompanyElement, "<Button-1>", OpenCompany)

额外修正点

  • 原代码缺少root对象的初始化,需在代码开头补充:root = ttk.Window() 或 root = tk.Tk(),最后加上root.mainloop()启动事件循环。
  • 方法名CreatImage可修正为CreateImage(符合英文拼写规范,不影响功能)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 02:43:23