【问题标题】:How to easily avoid Tkinter freezing?如何轻松避免 Tkinter 冻结?
【发布时间】:2017-07-14 07:28:37
【问题描述】:

我开发了一个简单的 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()

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

非常感谢您的帮助。

【问题讨论】:

  • 你不能指望你的程序在doingALotOfStuff()忙的时候每秒都运行self.refresh。我认为你不会绕过多线程。
  • 我明白了。对我来说似乎很疯狂,没有简单的解决方案来做这样一个简单的软件......也许有人会告诉我们任何技巧!

标签: python user-interface tkinter


【解决方案1】:

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()

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

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

【讨论】:

  • 谢谢,感谢您的帮助。我认为主要问题是由于doingALotOfStull() 函数确实也在更新GUI……我想这里没有聪明的解决方案。我必须研究多线程,或者最终完全避免使用 GUI……
  • 如果我启动那个线程,Tk 永远不会开始运行。如果我尝试在 Tk 之后启动该线程,则该线程永远不会开始运行...
【解决方案2】:

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

如果你定义了任何函数,比如 combine() 导致 Tkinter 窗口冻结,然后创建另一个函数以在后台启动 combine(),如下所示:

import threading
def combine():
    ...

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

现在你必须打电话给start_combine_in_bg(),而不是打电话给combine() 我这样做了,现在我的窗户没有结冰,所以我在这里分享了它。请记住,您一次只能运行一个线程。

看看参考:stackoverflow - avoid freezing of tkinter window using one line multithreading code

【讨论】:

    【解决方案3】:

    这是我设法解决此问题的方法(也许我不知道它很脏):

    每当我通过doingALotOfStuff() 函数更新我的tkinter 窗口时,我都会调用myTk.update()

    它避免了我的冻结。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-03
      • 2020-07-16
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-02
      • 1970-01-01
      相关资源
      最近更新 更多