使用多帧渲染 class objects 时 Tkinter 图像不显示

Tkinter Image not Displaying when rendering class objects with multiple frames

我在 python3 中使用 Tkinter 创建了一个桌面应用程序。该应用程序有一个主要的 class object 'Stack',其中有一个函数可以在按钮单击事件中呈现多个帧以导航到应用程序中的其他 windows。

我正在尝试使用 PIL.ImageTk/PIL.Image 在 'HomePage' 屏幕上显示图像(实际上所有页面都作为标题)。每次我 运行 来自终端 (macOS) 的应用程序时,桌面应用程序 运行s 但图像没有出现。我究竟做错了什么?这是我的代码:


import getpass
import tkinter as tk
from tkinter import ttk
from PIL import ImageTk, Image

LARGE_FONT = ('Source Code Pro', 24)

class Stack(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)

        container = tk.Frame(self)
        container.pack(side='top', fill='both', expand=True)

        container.grid_rowconfigure(0, weight=1) 
        container.grid_columnconfigure(0, weight=1) 

        self.frames = {}

        for F in (HomePage, NdA):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky='news')
        self.show_frame(HomePage)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()

class HomePage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        username = getpass.getuser()
        logo_path = 'myfilepath'.format(username)
        img = ImageTk.PhotoImage(Image.open(logo_path+'myimage.png').resize((120,120)))
        l = tk.Label(self, image=img)
        l.grid(column=0, row=0, ipadx=10, ipady=5, sticky='w')
        ttk.Label(
            self, 
            text='Some Text',
            wraplength=450,
            justify=tk.LEFT
            ).grid(
                column=1, 
                row=0,
                ipady=10,
                padx=(0,10),  
                sticky='nw')

        tier1 = tk.Button(self, text='Button1', state=tk.DISABLED).grid(column=0, row=3, padx=10, columnspan=2, sticky='nesw')
        tier2 = tk.Button(self, text='Button2', state=tk.DISABLED).grid(column=0, row=4, padx=10, columnspan=4, sticky='nesw')
        tier3 = ttk.Button(self, text='Button3', command=lambda: controller.show_frame(Tier3))
        tier3.grid(column=0, row=5, padx=10, columnspan=4, sticky='nesw')

        nda = ttk.Button(self, text='Button4', command=lambda: controller.show_frame(NdA))
        nda.grid(column=0, row=6, padx=10, pady=(0,10), columnspan=4, sticky='nesw')

class NdA(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        def clear_form():
            effective_date.delete(0, END)
            client_name.delete(0, END)
            address.delete(0, END)
            user_initials.delete(0, END)

        def submit_data():
            functions.create_nda(
                date=effective_date.get(), 
                client_name=client_name.get(), 
                address=address.get(), 
                user=user_initials.get()
                )
            effective_date.delete(0, tk.END)
            client_name.delete(0, tk.END)
            address.delete(0, tk.END)
            user_initials.delete(0, tk.END)
            messagebox.showinfo('Heading Text', 'Message Text')

        tk.Label(
            self, 
            text='Some Text',
            wraplength=450,
            justify=tk.LEFT
            ).grid(
                column=1, 
                row=0,
                columnspan=3, 
                ipady=10,
                padx=(0,10),  
                sticky='nw')

        tk.Label(self, text='Label1').grid(column=0, row=2, pady=(20,10), columnspan=4, sticky='news')

        tk.Label(self, text='Data1').grid(column=0, row=3, padx=(10,0), sticky='w')
        client_name = tk.Entry(self, width=30)
        client_name.grid(column=1, row=3, columnspan=3, padx=(0,10), sticky='news')

        tk.Label(self, text='Data2').grid(column=0, row=5, padx=(10,0), sticky='w')
        address = tk.Entry(self, width=30)
        address.grid(column=1, row=5, columnspan=3, padx=(0,10), sticky='news')

        tk.Label(self, text='Data3').grid(column=0, row=6, padx=(10,0), sticky='w')
        effective_date = tk.Entry(self, width=30)
        effective_date.insert(1, ' mm/dd/yyyy')
        effective_date.grid(column=1, row=6, columnspan=3, padx=(0,10), sticky='news')

        tk.Label(self, text='Data4').grid(column=0, row=7, padx=(10,0), sticky='w')
        user_initials = tk.Entry(self, width=30)
        user_initials.grid(column=1, row=7, columnspan=3, padx=(0,10), sticky='news')

        create_tier3 = tk.Button(self, text='or click me', command=submit_data).grid(column=3, row=8, pady=(30,10), padx=(0,10), sticky='news')
        clear_form = tk.Button(self, text='click me', command=clear_form).grid(column=2, row=8, pady=(30,10), padx=(5,5), sticky='news')
        # return_home = tk.Button(self, text='HOME').grid(column=1, row=8, pady=(30,10), sticky='news')


app = Stack()
app.mainloop()

当 class 中的 __init__() 函数退出时 HomePage 名称 img 被垃圾收集,因此标签无法记住它。您需要保存对图像的引用。通常的做法是将其作为属性保存到标签中:

l = tk.Label(self, image=img)
l.image = img      # Save reference to image