Tkinter:如何检查根窗口是否已被销毁?

13
我正在使用Tkinter和线程编写应用程序。
问题是,在关闭主应用程序之后,仍然有一些线程在运行。我需要一种方法来检查根窗口是否已被销毁,以避免出现“TclError: can't invoke "wm" command”的错误。
我所知道的所有方法:wminfo_exists()和state()一旦根被销毁就会返回错误。

似乎你可以在wminfo_exists()函数调用周围加上try/except语句,假设任何TclError错误都意味着根已经不存在了。 - martineau
1
测试是否 tkinter._default_root 不为 None。 - Li-chih Wu
2个回答

11

如果有人遇到同样的问题,我会添加我的解决方法。 我遵循此处建议。 我拦截窗口关闭事件来设置标记,表示root已经被关闭,需要时检查该标记。

exitFlag = False

def thread_method():
    global root, exitFlag
    if not exitFlag:
        // execute the code relate to root

def on_quit():
    global exitFlag
    exitFlag = True
    root.destroy()

root.protocol("WM_DELETE_WINDOW", on_quit)

3
如果您正在使用类似以下的内容:
import Tkinter

root = Tkinter.Tk()
root.bind('<space>', lambda e: root.quit())  # quitting by pressing spacebar
root.mainloop()

如果你使用root.quit()而不是root.destroy(),那么quit方法会杀死Tcl解释器并退出主循环并删除所有小部件。因此,一旦你调用了root.quit(),你可以确定你的root已经完全关闭!
你建议的所有其他方法(例如:wminfo_exists())仅在至少存在一个有效的Tk时才可用。
注意:如果你正在使用多个主循环,你应该使用destroy方法来确保你的主要主循环不会被终止--但我认为这不是你的情况。

2
感谢您的回答。我遇到的问题是,在 root.quit() 之后,仍然有一些线程在运行,我需要让我的线程知道 root 已经死亡。目前,我只能拦截退出方法并设置全局变量来让我的线程知道 root 已经死亡。我想知道是否还有其他解决方案。 - bizi
1
root.winfo_exists()(没有'm')?无论如何,为什么不用try/except捕获该错误,当它发生时只需终止线程即可。 - Peter Varo
我正在关注有关线程的讨论,并且他们提到,在执行期间终止线程是一种不好的做法。这就是为什么我希望找到一种解决方案,让我的程序能够“平稳”地结束执行。 - bizi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接