使用“wait_variable()”时无法退出 tkinter 应用程序

Dav*_*ous 5 python tkinter python-3.x

我有一个包含tkinter窗口和其他正在运行的任务的 python 代码。

我一直在尝试将"WM_DELETE_WINDOW"事件绑定到一个函数,该函数在关闭窗口时退出我的 python 代码,但无法实现。

这是我的尝试:

def on_exit():
    root.destroy()
    sys.exit()
root.protocol('WM_DELETE_WINDOW', on_exit)
Run Code Online (Sandbox Code Playgroud)

窗口被成功销毁但python代码没有退出。有什么sys.exit()不工作的可能原因吗?

我究竟做错了什么?我应该尝试任何替代方法吗?

做了一些测试,我想出了可能是什么问题。

这是一个小代码,它总结了我的大得多的代码。

import tkinter as tk
import sys

root = tk.Tk()
submitted = tk.IntVar()

def on_exit():
    root.destroy()
    sys.exit()
root.protocol('WM_DELETE_WINDOW', on_exit)

def submit():
    submitted.set(1)
    print("submitted")

button= tk.Button(root, text="Submit",command=submit)
button.pack()
button.wait_variable(submitted)

root.mainloop()
Run Code Online (Sandbox Code Playgroud)

我现在相信这wait_variable是问题的根源。

当我添加submitted.set(1)on_exit()(或者如果我在关闭窗口之前先单击按钮)时,代码实际上会退出,但是如果我尝试在不按下按钮的情况下关闭窗口,代码将不会退出。

那么这是否意味着wait_variable不仅让 tkinter 应用程序等待,而且还阻止了 python 代码退出?!

我试过了os._exit(1),它奏效了,但我认为它不干净。

Mik*_*SMT 3

正如您更新的问题指出的那样,问题是wait_variable()。离开此方法的文档wait_variable()会进入一个本地事件循环,该循环不会中断该循环,mainloop但是似乎在该本地事件循环终止(变量以某种方式更新)之前,它将阻止 python 实例终止,因为仍然有一个活动的环形。因此,为了防止这种情况,您还正确地指出您需要在终止 tk 实例之前更新此变量。

\n

这可能看起来很奇怪,但这是我所期望的行为。据我了解,在 python 实例退出之前需要终止活动循环。

\n

正如 Bryan 在评论中指出的那样,该方法是“一个在嵌入式 tcl 解释器内调用vwaitwait_variable()命令的函数。这个 tcl 解释器对 python 异常一无所知,这可能就是它无法识别 sys.path 引发的 python 异常的原因。出口()”

\n

相关文档链接:

\n

等待变量()

\n

链接中的相关文字:

\n
\n

等待变量(名称)

\n
\n
\n

等待给定的 Tkinter 变量\n更改。此方法进入本地事件循环,因此应用程序的其他部分\n仍将响应。当变量更新时,本地事件循环终止(将其设置为当前值也有效)。

\n
\n

您还可以将变量设置为当前设置的任何值以终止此事件循环。

\n

这条线应该适合你:

\n
submitted.set(submitted.get())\n
Run Code Online (Sandbox Code Playgroud)\n

也就是说你实际上并不需要sys.exit()。您可以简单地使用root.destroy().

\n

您的新函数应如下所示:

\n
def on_exit():\n    submitted.set(submitted.get())\n    root.destroy()\n
Run Code Online (Sandbox Code Playgroud)\n

如果主循环之后没有更多代码,python 实例将自动关闭。

\n