Overriding Tkinter “X” button control (the button

2019-01-17 07:23发布

问题:

This question already has an answer here:

  • How do I handle the window close event in Tkinter? 4 answers

When the user presses a close Button that I created, some tasks are performed before exiting. However, if the user clicks on the [X] button in the top-right of the window to close the window, I cannot perform these tasks.

How can I override what happens when the user clicks [X] button?

回答1:

It sounds as if your save window should be modal.

If this is a basic save window, why are you reinventing the wheel? Tk has a tkFileDialog for this purpose.


If what you want is to override the default behaviour of destroying the window, you can simply do:

root.protocol('WM_DELETE_WINDOW', doSomething)  # root is your root window

def doSomething():
    # check if saving
    # if not:
    root.destroy()

This way, you can intercept the destroy() call when someone closes the window (by any means) and do what you like.



回答2:

Using the method procotol, we can redefine the WM_DELETE_WINDOW protocol by associating with it the call to a function, in this case the function is called on_exit:

import tkinter as tk
from tkinter import messagebox


class App(tk.Tk):

    def __init__(self):
        tk.Tk.__init__(self)
        self.title("Handling WM_DELETE_WINDOW protocol")
        self.geometry("500x300+500+200")
        self.make_topmost()
        self.protocol("WM_DELETE_WINDOW", self.on_exit)

    def on_exit(self):
        """When you click to exit, this function is called"""
        if messagebox.askyesno("Exit", "Do you want to quit the application?"):
            self.destroy()

    def center(self):
        """Centers this Tk window"""
        self.eval('tk::PlaceWindow %s center' % app.winfo_pathname(app.winfo_id()))

    def make_topmost(self):
        """Makes this window the topmost window"""
        self.lift()
        self.attributes("-topmost", 1)
        self.attributes("-topmost", 0)


if __name__ == '__main__':
    App().mainloop()


回答3:

The command you are looking for is wm_protocol, giving it "WM_DELETE_WINDOW" as the protocol to bind to. It lets you define a procedure to call when the window manager closes the window (which is what happens when you click the [x]).



回答4:

I found a reference on Tkinter here. It's not perfect, but covers nearly everything I ever needed. I figure section 30.3 (Event types) helps, it tells us that there's a "Destroy" event for widgets. I suppose .bind()ing your saving jobs to that event of your main window should do the trick.

You could also call mainwindow.overrideredirect(True) (section 24), which disables minimizing, resizing and closing via the buttons in the title bar.