Overriding Tkinter "X" button control (the button that close the window)

Question:

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?

Asked By: erkangur

||

Answers:

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.

Answered By: user395760

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.

Answered By: Nick Presta

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]).

Answered By: Bryan Oakley

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()
Answered By: The Demz
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.