在 Tkinter 应用程序关闭时执行任务



当我的Tkinter应用程序结束时,它必须执行一些工作(例如,将一些数据存储到文件中)。在某些情况下,应该询问用户是否真的要关闭应用程序。

有多种方法可以关闭 Tkinter 应用程序:

  • 窗口上的 X
  • 一个按钮
  • 菜单栏中的条目

我怎样才能捕捉到所有这些"事件"?

#!/usr/bin/env python3
from tkinter import *
def on_delete_window():
print('on_delete_window')
print('save my data')

if __name__ == '__main__':
root = Tk()
Button(root, text='Destroy', command=root.destroy).pack()
Button(root, text='Quit', command=root.quit).pack()
menu = Menu(root)
menu.add_command(label='Destroy', command=root.destroy)
menu.add_command(label='Quit', command=root.quit)
root.config(menu=menu)
# this catches ONLY the X in the window
# but none of the two buttons!
root.protocol('WM_DELETE_WINDOW', on_delete_window)
root.mainloop()

一种解决方法是定义一个closing_procedure方法,该方法接受callback参数,该参数根据对messagebox对话框的回复进行回调,例如,您将所有关闭操作重定向到该对话框。

try:                        # In order to be able to import tkinter for
import tkinter as tk    # either in python 2 or in python 3
import tkinter.messagebox as tkmb
except ImportError:
import Tkinter as tk
import tkMessageBox as tkmb

def closing_procedure(callback, *args, **kwargs):
response = tkmb.askyesno("Quit", "Do you really want to close?")
if response:
callback(*args, **kwargs)
else:
print("Closing cancelled!")

if __name__ == '__main__':
root = tk.Tk()
button = tk.Button(root, text="Quit",
command=lambda : closing_procedure(root.quit))
button.pack()
root.protocol('WM_DELETE_WINDOW',
lambda : closing_procedure(root.destroy))
root.mainloop()

如果要在单个调用中捕获所有内容,请绑定到根窗口的<Destroy>事件。无论它如何销毁,您的函数都将被调用。不过要小心 - 绑定到根窗口的事件被每个小部件捕获。仅当根窗口被销毁时,才需要执行最终操作。

如果你想问用户他们是否确定他们何时通过窗口管理器关闭窗口,你需要像你所做的那样将函数绑定到WM_DELETE_WINDOW协议。如果你想询问他们是否确定退出按钮或菜单,你必须将对话框添加到这些小部件调用的任何函数中。

请注意,<Destroy>绑定仅在窗口被销毁发生,此时请求确认为时已晚。您可以将代码放在销毁函数中以自动保存,但您必须在销毁应用程序之前将确认放在调用的函数中。

import tkinter as tk
def on_destroy(event):
if event.widget.winfo_parent() == "":
print("program is exiting...")
root = tk.Tk()
label = tk.Label(root, text="Hello, world")
label.pack(fill="both", padx=20, pady=20)
root.bind("<Destroy>", on_destroy)
root.mainloop()

最新更新