繁体   English   中英

为什么我的Tkinter布局发生变化?

[英]Why is my tkinter layout changing?

我制作了这个tkinter应用程序,但是我遇到了一个错误,该错误中的布局发生了变化,底部的按钮消失了。

我无法100%复制该错误。 它发生在随机时间。 由于这个原因,该SSCCE可能包含超出其需要的内容。 它仍然比我原来的应用程序少很多。

from random import random
from threading import Thread, Lock
from time import sleep
from tkinter import Tk, LEFT, RIGHT, BOTH, X, Y, Listbox, Scrollbar, VERTICAL, END
from tkinter.ttk import Frame, Button, Style, Entry


class ListManager:
    def __init__(self, ui):
        self.entry_list = []

        self.ui = ui  # to notify of list update

        self.timer = ListManager.interval + 1
        self.stop = False

    interval = 1  # between updates

    @staticmethod
    def api_request() -> dict:
        new_list = ["line"]
        while random() > .4:
            new_list.append("line")
        return {"data": new_list}

    def get_entries(self):
        r = self.api_request()

        self.entry_list = []

        for line in r["data"]:
            self.entry_list.append(line)

    def run(self):
        self.timer = ListManager.interval + 1
        while not self.stop:
            if self.timer > ListManager.interval:
                self.get_entries()

                if self.ui is None:
                    print("entries:", len(self.entry_list))
                    for entry in self.entry_list:
                        print(entry)
                else:
                    self.ui.receive(self.entry_list)
                self.timer = 0
            else:
                self.timer += 1
            sleep(1)


class UI(Frame):
    def __init__(self):
        super().__init__()

        self.style = Style()

        self.listbox = None
        self.name_entry = None
        self.entries = []
        self.mutex = Lock()

        self.init_pack()

    def init_pack(self):
        # TODO: investigate open button disappearing (probably need to repack in receive function)
        self.master.title("list")
        self.style.theme_use("default")

        add_streamer_frame = Frame(self)
        add_button = Button(add_streamer_frame, text="Add Line")
        add_button.pack(side=RIGHT, padx=5, pady=5)
        self.name_entry = Entry(add_streamer_frame)
        self.name_entry.pack(fill=X, padx=5, expand=True)
        add_streamer_frame.pack(fill=X)

        list_frame = Frame(self)
        self.listbox = Listbox(list_frame, height=20)
        self.listbox.configure(font=("Courier New", 12, "bold"))
        scrollbar = Scrollbar(self.listbox, orient=VERTICAL)
        self.listbox.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.listbox.yview)
        scrollbar.pack(side=RIGHT, fill=Y)
        self.listbox.pack(fill=BOTH, padx=5, expand=True)
        list_frame.pack(fill=BOTH, expand=True)

        self.pack(fill=BOTH, expand=True)

        open_button = Button(self, text="Open")
        open_button.pack(side=LEFT, padx=5, pady=5)

    def receive(self, entries):
        self.mutex.acquire()

        self.listbox.delete(0, END)
        self.entries = []
        for entry in entries:
            self.listbox.insert(END, entry)
            self.entries.append(entry.split(" ")[0])

        self.mutex.release()


def main():
    root = Tk()
    root.geometry("800x400+300+300")
    app = UI()

    tl = ListManager(app)
    thread = Thread(target=tl.run)
    thread.start()

    root.mainloop()

    tl.stop = True
    thread.join()


if __name__ == "__main__":
    main()

通常情况下,这是通常的样子,应该是这样的:

正常正确

错误出现后的样子如下:

底部按钮消失了

加:

self.ui.update_idletasks()

后:

sleep(1)

要么:

更换:

self.listbox = Listbox(list_frame, height=20)

与:

self.listbox = Listbox(list_frame)
# or self.listbox = Listbox(list_frame, height=17)

必须保证的是,在进行过多操作时,没有时间花费在更新GUI上。 在不将sleep参数降低至0.001情况下,我无法直接重现第二张屏幕截图。

问题的根源似乎是,每次将某些东西添加到listbox它的高度(以像素单位的 winfo_height )都会重新计算,并从20个字符的高度减小到17,这并不总是那么长插入。

基本上,你的widget 不一定始终具有固定的20个字符的高度,它会调整根据其内容及其他工具,除非传播是通过调用禁用 self.listbox.pack_propagate(False)


加:

print(self.ui.listbox.winfo_height())

后:

sleep(1)

看看它的高度如何改变。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM