29

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?

nbro
  • 15,395
  • 32
  • 113
  • 196
erkangur
  • 2,048
  • 5
  • 21
  • 31

4 Answers4

58

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.

nbro
  • 15,395
  • 32
  • 113
  • 196
Nick Presta
  • 28,134
  • 6
  • 57
  • 76
10

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()
nbro
  • 15,395
  • 32
  • 113
  • 196
The Demz
  • 7,066
  • 5
  • 39
  • 43
  • [Intercept Tkinter “Exit” command?](http://stackoverflow.com/questions/4643007/intercept-tkinter-exit-command) – The Demz Nov 09 '12 at 12:58
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]).

nbro
  • 15,395
  • 32
  • 113
  • 196
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
1

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.

  • overrideredirect(flag=None) [#] Sets or gets the override redirect flag. If non-zero, this prevents the window manager from decorating the window. In other words, the window will not have a title or a border, and it cannot be moved or closed via ordinary means. – Jacob Jan 20 '18 at 17:36