Message Box Dialog at Exit using Tkinter in Python

Viewed 3291

I want to show a message box dialog when pressing the "X" button to close the GUI. I want to ask the user if he's sure he wants to exit the program with a Yes/No choice. I'm getting an error when I press "Yes" in the dialog and the GUI closes if I press "NO". This is the full code

This is the error I'm getting:

self.tk.call('destroy', self._w)

_tkinter.TclError: can't invoke "destroy" command: application has been destroyed

This is what I've done so far:

import atexit

def deleteme():
     result = messagebox.askquestion("Exit", "Are You Sure You Want to Exit?")
     if result == "yes":
        root.destroy()
     else:
        return None

atexit.register(deleteme)
2 Answers

You can use the protocol method to bind the window deletion with a function.

from tkinter import *
from tkinter import messagebox

def on_close():
    response=messagebox.askyesno('Exit','Are you sure you want to exit?')
    if response:
        root.destroy()

root=Tk()
root.protocol('WM_DELETE_WINDOW',on_close)

root.mainloop()

UPDATE

According to the docs of atexit module

Functions thus registered are automatically executed upon normal interpreter termination.

The function registered was called after the mainloop was destroyed (since nothing proceeds, it marks the end of program). The GUI element that the function tries to destroy doesn't exist anymore, as also stated by the error.

This module is not meant for the use case you trying to achieve, it's usually used for "cleanup" functions that are supposed to perform a task after the program terminates.

The callback registered via the WM_DELETE_WINDOW protocol gives you the control over what happens when the window is instructed to close.

Just to add to @AST's answer:

You are trying to use the atexit library to block closing the tkinter window when the program tries to exit. The problem is that the atexit library calls your function after the window is destroyed. I don't even think that you can block your program exiting using the atexit. That is why @AST suggested using root.protocol("WM_DELETE_WINDOW", on_close) which runs when the tkinter window is trying to close (works only when the user presses the "X" button).

Related