如何轻松避免 Tkinter 冻结?

新手上路,请多包涵

我开发了一个简单的 Python 应用程序来做一些事情,然后我决定使用 Tkinter 添加一个简单的 GUI。

问题是,当 main 函数正在做它的事情时,窗口冻结了。

我知道这是一个常见问题,我已经读到我应该使用多线程(非常复杂,因为该函数也会更新 GUI)或将我的代码划分为不同的函数,每个函数工作一段时间。无论如何,我不想为这样一个愚蠢的应用程序更改我的代码。

我的问题是:是否有可能没有简单的方法每秒更新我的 Tkinter 窗口?我只想应用 KISS 规则!

我将在下面给你一个我试过但没有用的伪代码示例:

     class Gui:
        [...]#costructor and other stuff

        def refresh(self):
            self.root.update()
            self.root.after(1000,self.refresh)

        def start(self):
            self.refresh()
            doingALotOfStuff()

    #outside
    GUI = Gui(Tk())
    GUI.mainloop()

它只会执行一次刷新,我不明白为什么。

非常感谢你的帮助。

原文由 decadenza 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 671
2 个回答

Tkinter 在 mainloop 中。这基本上意味着它不断刷新窗口,等待单击按钮,键入单词,运行回调等。当您在 mainloop 开启的同一线程上运行一些代码时,则没有其他任何东西将在 mainloop 上执行,直到该部分代码完成。一个非常简单的解决方法是将一个长时间运行的进程生成到一个单独的线程上。这仍然能够与 Tkinter 通信并更新它的 GUI(大部分)。

这是一个简单的示例,不会彻底修改您的伪代码:

 import threading

class Gui:
    [...]#costructor and other stuff

    def refresh(self):
        self.root.update()
        self.root.after(1000,self.refresh)

    def start(self):
        self.refresh()
        threading.Thread(target=doingALotOfStuff).start()

#outside
GUI = Gui(Tk())
GUI.mainloop()

答案详细介绍了 mainloop 以及它如何阻止您的代码。

这是 另一种方法,它在它自己的线程上启动 GUI,然后运行不同的代码。

原文由 double_j 发布,翻译遵循 CC BY-SA 3.0 许可协议

使用 thread 模块在 python 中使用 多线程 可以避免“无响应”问题。

如果你已经定义了任何函数,比如 combine() 由于 Tkinter 窗口冻结,然后在后台启动另一个函数 combine() 如下所示:

 import threading
def combine():
    ...

def start_combine_in_bg():
    threading.Thread(target=combine).start()

现在不是调用 combine() ,而是必须调用 start_combine_in_bg() 我这样做了,现在我的窗口没有冻结,所以我在这里分享它。请记住,您一次只能运行一个线程。

查看参考资料: stackoverflow - avoid freeze of tkinter window using one line multithreading code

原文由 Prashantzz 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题