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
相关产品推荐
相关产品推荐

