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

时间:2018-02-03 23:16:58

标签: python python-3.x events 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()

2 个答案:

答案 0 :(得分:2)

如果要在一次调用中捕获所有内容,请绑定到根窗口的<Destroy>事件。无论它如何被破坏,你的函数都会被调用。但要小心 - 每个小部件都会捕获绑定到根窗口的事件。只有当它是被销毁的根窗口时,您才会想要做最后的操作。

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

请注意<Destroy>上的绑定只有在窗口被销毁后才会发生,此时要求确认将为时已晚。您可以将代码置于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()

答案 1 :(得分:2)

一种解决方法是定义一个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()