python - PIL 照片图像不显示在 Tkinter 上
问题描述
我知道这是一个常见问题,但我自己似乎无法解决。我的图像不显示在 Tkinter 上。我做了研究,似乎问题出在垃圾收集上。我尝试了一切来阻止它,但似乎没有任何效果。这是我的完整代码:
import tkinter as tk
from tkinter import ttk
from lxml import etree
from os import walk
from PIL import Image, ImageTk
class Gui(tk.Tk):
def __init__(self):
super().__init__()
self.frames = {}
self.l_widgets = {}
self.images = [] # Unused, doesn't work (nor does a dictionary)
# self.arbre = etree.parse("characters.xml") #relative path
self.arbre = etree.parse("C:/Users/nolan/OneDrive/Bureau/Code/wovnot/characters.xml") # absolute path
self.roles = {}
for root in self.arbre.xpath('//wolvesville'):
for pool in root.xpath('pool'):
self.roles[str(pool.get("name"))] = {}
for role in pool.xpath("character"):
self.roles[str(pool.get("name"))][role.get("name")] = (
role.get("surname"),
role.get("surname2"),
"r" + role.get("random"))
self.command = {}
def add_frame(self, name, grid_args=None, frame="main"):
if grid_args is None:
grid_args = {}
if frame == "main":
self.frames[name] = ttk.Frame(self)
else:
self.frames[name] = ttk.Frame(self.frames[frame])
self.frames[name].grid(**grid_args)
def create_entry(self, name, config_args=None, grid_args=None, frame="main"):
if grid_args is None:
grid_args = {}
if config_args is None:
config_args = {}
if frame == "main":
self.l_widgets[name] = (ttk.Entry(self), tk.StringVar())
else:
self.l_widgets[name] = (ttk.Entry(self.frames[frame]), tk.StringVar())
self.l_widgets[name][0].config(textvariable=self.l_widgets[name][1], **config_args)
self.l_widgets[name][0].grid(**grid_args)
def create_notebook(self, name, config_args=None, grid_args=None, frame="main"):
if grid_args is None:
grid_args = {}
if config_args is None:
config_args = {}
if frame == "main":
self.l_widgets[name] = (ttk.Notebook(self, **config_args), 0)
else:
self.l_widgets[name] = (ttk.Notebook(self.frames[frame], **config_args), 0)
self.l_widgets[name][0].grid(**grid_args)
def add_image(self, name, filename, size=(None, None)):
"""Unused, doesn't work"""
image_temp = Image.open(filename)
if size != (None, None):
image_temp.thumbnail(size)
image = ImageTk.PhotoImage(image_temp)
self.images[name] = image
return image
def create_a_label_with_an_image(self, name, filename, size=(None, None), config_args=None, grid_args=None,
frame="main"):
global immortals
if grid_args is None:
grid_args = {}
if config_args is None:
config_args = {}
immortals[name] = ImagePersistent(filename, size).image
self.l_widgets[name] = (ttk.Label(self.frames[frame]), immortals[name])
self.l_widgets[name][0].config(**config_args)
self.l_widgets[name][0].image = immortals[name]
self.l_widgets[name][0].grid(**grid_args)
def add_to_notebook(self, name, name_frame, config_args=None, grid_args=None):
if grid_args is None:
grid_args = {}
if config_args is None:
config_args = {}
self.frames[name_frame] = ttk.Frame(self)
self.l_widgets[name][0].add(self.frames[name_frame], **config_args)
self.l_widgets[name][0].grid(**grid_args)
class ImagePersistent:
def __init__(self, path, size=(None, None)):
self.path = path
self.temp = Image.open(path)
if size != (None, None):
self.temp.thumbnail(size)
self.image = ImageTk.PhotoImage(self.temp)
# END################################################################################################################################################################"""
global immortals
immortals = {}
# also tried globals().update({"immortals":{}})
# and immortals.update({name: thing})
g = Gui()
# mypath = "icons/characters"
mypath = "C:/Users/nolan/OneDrive/Bureau/Code/wovnot/icons/characters"
filenames = next(walk(mypath), (None, None, []))[2] # [] if no file
if not filenames:
raise Warning("no icons found")
print(filenames)
g.create_notebook("roles", grid_args={"rowspan": 4, "column": 0})
for pool in g.roles.keys():
g.add_to_notebook("roles", str(pool), config_args={"text": str(pool)})
nbr_images = 0
for icon in filenames:
if icon[:-4] in g.roles[pool].keys():
g.create_a_label_with_an_image(icon[:-4], mypath + "/" + icon,
size=(50, 50),
grid_args={"row": nbr_images // 12,
"column": nbr_images % 12},
frame=str(pool))
nbr_images += 1
g.mainloop()
这是似乎与其他人一起使用的垃圾收集解决方案并没有解决问题:
- 将每个图像作为变量引用。在我的情况下是不可能的(我不知道我一开始有多少)并且在尝试为一张图像执行此操作时,它仍然没有显示。
- 使用 label.image = image 保持参考。它在我的代码中,不起作用。
self.l_widgets[name][0].image = immortals[name]
,线 - 使用一个类。ImagePersistent 类也不起作用。
- 使用列表/字典/元组。self.images 不起作用,不把它放在 self.l_widgets
- 使用全局变量。不死之身行不通。我还尝试了 globals().update({"immortals":{}}) 和 immortals.update({name: thing})。
所以我不知道。它仍然是网格化的,当我不使用类时它起作用了!我觉得我什么都试过了。如果需要,我可以提供指向图像(所有 RGBA png)的链接。我知道它们确实存在,因为 nbr_images 值达到 57。
解决方案
我忘了把图像作为配置部分的属性。此代码有效:
def create_a_label_with_an_image(self, name, filename,size=(None,None), config_args=None, grid_args=None, frame="main"):
global immortals
if grid_args is None:
grid_args = {}
if config_args is None:
config_args = {}
immortals[name] = ImagePersistent(filename, size).image
self.l_widgets[name] = (ttk.Label(self.frames[frame]), immortals[name])
self.l_widgets[name][0].config(**config_args, image=immortals[name])
self.l_widgets[name][0].image = immortals[name]
self.l_widgets[name][0].grid(**grid_args)
感谢@acw1668 告诉我。我会关闭这个话题。