【问题标题】:Tkinter Label display and disappear when they are createdTkinter 标签在创建时显示和消失
【发布时间】:2024-04-18 05:30:01
【问题描述】:

在创建框架并使用 root.mainloop 启动 GUI 后,我正在尝试向框架添加新标签(我可能会切换到按钮,但我认为行为是相同的)

代码如下:

import tkinter as tk
import config
import os
from PIL import ImageTk, Image

class JulieGui():
    dirLabels = []
    def __init__(self, queue):
        self.currentDirDisplayed = False
        root = tk.Tk()
        self.root = root
        self.root.geometry("600x400+0+0")
        self.root.title("Julie")
        self.currentDirLabel = tk.Label(self.root, text="Current dir : ", font="Arial 12", width=600)
        self.currentDirLabel.pack()
        queue.put(self)
        self.run()

def updateDir(self):
    self.currentDir.set(self.currentDirPath)

def runLoop(self):
    self.currentDirLabel.configure(text="CurrentDir : {}".format(config.currentDirPath))
    self.printCurrentDir()
    self.root.after(200, self.runLoop)

def printCurrentDir(self):
    if config.currentDirChanged or not self.currentDirDisplayed:
        print("showing dir")
        self.currentDirDisplayed = True
        nbFiles = 0;
        x = 0
        y = 50
        for f in config.currentDirContent:
            if os.path.isdir(f):
                print("file : {}".format(f))
                print("nb labels : {}".format(len(self.dirLabels)))
                frame = tk.Frame(self.root, width= 500, height = 500, bd = 2, relief = tk.GROOVE)
                frame.place(x = 10, y = 50)
                directory = ImageTk.PhotoImage(Image.open('/home/olivier/git/linuxAssistant/resources/images/directory.jpg'))
                self.dirLabels.append(tk.Label(frame, image = directory, text = "plop", compound = tk.CENTER))
                self.dirLabels[nbFiles].place(x=x, y=y)
                frame.update()
                print("x : {}".format(x))
                print("y : {}".format(y))
                nbFiles += 1
                if nbFiles % 10 == 0:
                    x = 0
                    y += 60
                else:
                    x += 60

def run(self):
    print("starting gui")
    self.root.after(200, self.runLoop)
    self.root.mainloop()
    print("gui started")

def quit(self):
    self.root.after(0, self.root.destroy)

所以我正在创建一个只有 1 个标签的窗口并使用 self.root.mainloop() 启动 tkinter。 我也在使用 root.after 来不断更新带有 runLoop(self) 的窗口

这个 runLoop 正在调用一个 printCurrentDir 函数,该函数应该为找到的每个目录显示一个带有图标的标签。

创建的 tk.Frame 显示正确,但标签在创建后立即消失。 因此,当我运行代码时,我看到第一个标签,然后在显示第二个标签时它消失了...... 所有标签都已创建,但没有一个标签留在屏幕上。

如果我不使用 frame.update 或 self.root.update,则根本不会显示标签 如果我用 self.root.mainloop() 替换它,代码就会停在上面,这看起来很正常。

列表内容 (config.currentDirContent) 和 config.currentDirChanged 值会在第二个线程需要时更新。

整个类在另一个类的线程函数中启动。 我对另一个没有问题的 tkinter 类使用相同的行为

为了更容易理解,这里有两张截图,在添加了第一个和第二个标签之后:

1rst label added

Second label added

在第二次捕获时,我应该有 2 个标签。

第二个问题,我的标签是用图像和文本创建的(用于测试)。但是,文本不显示。

知道我为什么会出现这种行为以及如何解决它吗?

【问题讨论】:

    标签: python tkinter label


    【解决方案1】:

    您在 printCurrentDir() 函数内的 for 循环的每次迭代中创建了新框架(内部有一个标签),并将框架放在相同的位置。所以最后一帧将覆盖在所有先前创建的帧之上。您应该在 for 循环之外创建框架。

    同样的图像directory在for循环内创建,它也应该在for循环外创建,并将其更改为实例变量self.directory以避免垃圾收集。

        def printCurrentDir(self):
            if config.currentDirChanged or not self.currentDirDisplayed:
                print("showing dir")
                self.currentDirDisplayed = True
                nbFiles = 0;
                x = 0
                y = 50
    
                frame = tk.Frame(self.root, width=600, height=600, bd=2, relief=tk.GROOVE)
                frame.place(x=10, y=50)
                self.directory = ImageTk.PhotoImage(file='/home/olivier/git/linuxAssistant/resources/images/directory.jpg')
                for f in config.currentDirContent:
                    if os.path.isdir(f):
                        print("file : {}".format(f))
                        print("nb labels : {}".format(len(self.dirLabels)))
                        self.dirLabels.append(tk.Label(frame, image=self.directory, text="plop", compound=tk.CENTER))
                        self.dirLabels[nbFiles].place(x=x, y=y)
                        #frame.update()
                        print("x : {}".format(x))
                        print("y : {}".format(y))
                        nbFiles += 1
                        if nbFiles % 10 == 0:
                            x = 0
                            y += 60
                        else:
                            x += 60
    

    【讨论】:

    • 它工作正常。谢谢。那么当标签添加到循环中时,python 不会保留对图像的引用以避免垃圾收集器? (我两周前才开始使用 python :))
    • 图像正常工作,但我仍然没有将文本添加到标签中。你也有这方面的想法吗?
    • 我在运行代码时显示文本“plop”。
    • 好的,那么这可能是我设备上的配置错误。我会继续寻找。再次感谢
    • 你的图片尺寸是多少?如果大于 60x60 像素,则标签可能会放在标签的可视区域之外。