tkinter中canvas.create_image返回值能否存入列表?该如何正确操作?
问题解答
1. create_image返回值相关说明
canvas.create_image()的返回值就是对应画布元素的整数ID,类型为int属于正常情况,完全可以存入列表,你打印得到的[1, 2]就是创建的两个图片元素的合法ID,后续可以通过这些ID对画布上的图片进行移动、修改属性、删除等操作,存ID的操作本身没有错误。
2. 前期图片消失的原因
图片消失和存ID的操作无关,是Tkinter的PhotoImage对象垃圾回收机制导致的:Tkinter底层不会持有ImageTk.PhotoImage实例的引用计数,当Python侧没有任何存活变量引用该实例时,实例就会被垃圾回收,画布上对应的图片就无法渲染显示。
你当前代码中第一个photoImg在第二张图片创建完成后没有被其他变量持有,因此被回收,第一张图随之消失;第二个photoImg2仍有变量引用,所以可以正常显示。
3. 正确实现方式
你需要额外维护一个列表,专门存储所有ImageTk.PhotoImage实例,保证图片显示期间实例不会被回收,参考修改后的代码:
from PIL import Image from PIL import ImageTk import tkinter as tk # 初始化根窗口 root = tk.Tk() # 分别存储画布元素ID、PhotoImage实例 canvas_image_ids = [] canvas_photo_images = [] canvas = tk.Canvas(root, width=640, height=640) canvas.pack() # 第一张图 img = Image.open(imgDirectory) img = img.resize((170, 170), Image.ANTIALIAS) photo_img = ImageTk.PhotoImage(img) canvas_image_ids.append(canvas.create_image(100, 100, image=photo_img)) canvas_photo_images.append(photo_img) # 保留实例引用,避免被回收 # 第二张图 img2 = Image.open(imgDirectory2) img2 = img2.resize((170, 170), Image.ANTIALIAS) photo_img2 = ImageTk.PhotoImage(img2) # 坐标调整为300,100避免两张图重叠 canvas_image_ids.append(canvas.create_image(300, 100, image=photo_img2)) canvas_photo_images.append(photo_img2) # 保留实例引用 print(canvas_image_ids) print(type(canvas_image_ids[0])) root.mainloop()
如果不需要单独维护ID,也可以将ID和PhotoImage实例以元组形式存入同一个列表,只要保证PhotoImage实例在图片显示周期内始终被引用即可。
内容的提问来源于stack exchange,提问作者ChociiMilk
相关产品推荐
相关产品推荐

