首页 > 解决方案 > 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()

这是似乎与其他人一起使用的垃圾收集解决方案并没有解决问题:

  1. 将每个图像作为变量引用。在我的情况下是不可能的(我不知道我一开始有多少)并且在尝试为一张图像执行此操作时,它仍然没有显示。
  2. 使用 label.image = image 保持参考。它在我的代码中,不起作用。self.l_widgets[name][0].image = immortals[name],线
  3. 使用一个类。ImagePersistent 类也不起作用。
  4. 使用列表/字典/元组。self.images 不起作用,不把它放在 self.l_widgets
  5. 使用全局变量。不死之身行不通。我还尝试了 globals().update({"immortals":{}}) 和 immortals.update({name: thing})。

所以我不知道。它仍然是网格化的,当我不使用类时它起作用了!我觉得我什么都试过了。如果需要,我可以提供指向图像(所有 RGBA png)的链接。我知道它们确实存在,因为 nbr_images 值达到 57。

标签: pythontkintergarbage-collectionpython-imaging-library

解决方案


我忘了把图像作为配置部分的属性。此代码有效:

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 告诉我。我会关闭这个话题。


推荐阅读