我知道这是一个常见的问题,但我似乎不能自己解决它。我的图片在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()
以下是垃圾收集的解决方案,这些解决方案似乎与其他解决方案一起工作并没有解决问题:
- 将每个图像引用为变量。在我的情况下是不可能的(我不知道我一开始有多少),而试图为一个图像做这个,它仍然没有显示。
- 保持标签的引用。Image = Image。这是我的代码,不起作用。li>使用类。ImagePersistent类也不能工作。
- 使用列表/字典/元组。自我。images不能工作,也不能把它放在self。l_widgets
- 使用全局变量。神仙不工作。我还尝试了globals().update({"immortals":{}})和immortals。更新({name:东西})。
所以我不知道。它仍然是网格的,当我不使用类时,它工作了!我觉得我什么都试过了。如果需要,我可以提供链接到图像(所有RGBA ping)。我知道它们确实存在,因为nbr_images的值变成了57。
我忘记把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, image=immortals[name])
self.l_widgets[name][0].image = immortals[name]
self.l_widgets[name][0].grid(**grid_args)
谢谢@acw1668告诉我。我要关闭主题。