tkinter.Tk的 "quit "方法退出了 "mainloop "事件处理程序,而 "destroy "则销毁了所有嵌入的小部件,只有
then
退出 "主循环"。那么,"摧毁 "是两者中更好的吗?嗯,有时不是。如果 "destroy "由于某种原因不能销毁所有的部件,那么 "mainloop "就不会被退出,Python 就会被锁定。最好是让 Python 在脚本结束时有秩序地关闭东西。
例如,如果你在一个 Tkinter 窗口中嵌入一个 Matplotlib 绘图,这很有用,因为 Matplotlib 自己的部件使用起来有点笨重。不幸的是,如果你试图通过点击标题栏中常见的 "X "来关闭这个窗口,窗口会正常关闭,但Python会继续运行。如果这个脚本是从终端启动的,你必须按Ctrl-C键几分钟后才能回到提示符。原因是关闭窗口的事件被绑定到 "destroy "上,这并没有销毁Matplotlib对象,而是让它们成为了孤儿。
解决的办法是将关闭窗口的事件绑定到 "退出 "上。但是......如果脚本是在一个基于Tkinter的IDE中启动的,比如IDLE,那么就会产生一个新的问题,即窗口不会关闭,因为IDLE保持着Tkinter的运行。所以现在必须在mainloop之后加上 "destroy"。最后,一切都好了。
下面是一个Matplotlib绘图的最小例子,按一下Tkinter按钮就可以反转。它的窗口可以顺利关闭。但是如果窗口关闭事件被绑定到 "destroy "而不是 "quit",那么一个被锁定的Python进程就会保留下来。
#!/usr/bin/env python3
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
root = tk.Tk()
data, = plt.plot([0,5,3,4,-5,3])
canvas = FigureCanvasTkAgg(plt.gcf(), master=root)
invert = lambda: (data.set_ydata(-data.get_ydata()), canvas.draw())
tk.Button(master=root, text="Invert", command=invert).pack()
canvas.get_tk_widget().pack(fill=tk.BOTH, expand=1)
root.protocol("WM_DELETE_WINDOW", root.quit)
root.mainloop()
root.destroy()
编辑:我补充一下,通过将窗口关闭事件绑定到both方法,你可以避免在 "mainloop "之后添加一行,如果因为某些原因需要这样做的话。
root.protocol("WM_DELETE_WINDOW", lambda: (root.quit(), root.destroy()))