In Python3/tkinter how to intercept when the user clicks the close button on a Toplevel window In Python3/tkinter how to intercept when the user clicks the close button on a Toplevel window tkinter tkinter

In Python3/tkinter how to intercept when the user clicks the close button on a Toplevel window


You want to use the wm_protocol method of the toplevel widget. Specifically with the WM_DELETE_WINDOW protocol.

>>> import tkinter as tk>>> root = tk.Tk()>>> dlg = tk.Toplevel(root)>>> dlg.wm_title("dialog")''>>> root.wm_protocol("WM_DELETE_WINDOW", lambda: print("close root"))''>>> dlg.wm_protocol("WM_DELETE_WINDOW", lambda: print("close dialog"))''>>> root.mainloop()close dialogclose root

The last lines are output when I click the window frame close button (the big red X). This now doesn't exit when I click this and is also called for Alt-F4 on either of the Tk windows.

The Tk documentation has more to say. The python documentation I found seemed rather sparse.


Just posting the full working code after following the advice from patthoyts.

#!/usr/bin/python3import tkinter as tkfrom tkinter import ttkimport tkinter.fontclass baseApp(ttk.Frame):    def __init__(self,master,*args,**kwargs):        super().__init__(master,*args,**kwargs)        self.master = master        self.mainframe = ttk.Frame(master)        self.topframe = ttk.Frame(self.mainframe, padding="5 8 5 5")        self.topframe.pack(side=tk.TOP, fill=tk.X)        self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH)class App(baseApp):    def __init__(self,master,*args,**kwargs):        super().__init__(master,*args,**kwargs)        self.master = master        self.button1 = ttk.Button(self.topframe,text="One",command=self.button_one)        self.btn_remessas = ttk.Button(self.topframe,text="Open/close Toplevel window",command=self.create_window2)        self.button1.grid(row=0,column=0)        self.btn_remessas.grid(row=0,column=1)        self.topframe.pack(side=tk.TOP, fill=tk.X)        self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH)    def create_window2(self):        if current_state.window2_open == False:            self.newWindow2 = tk.Toplevel(self.master)            self.newWindow2.geometry('600x500+680+0')            self.newWindow2.title('Second window')            self.janela_remessas = SecondWindow(self.newWindow2)            current_state.window2_open = True            self.newWindow2.wm_protocol("WM_DELETE_WINDOW", lambda: self.close_window2())                else:            self.close_window2()    def close_window2(self, *event):        print("closing window")        root.update_idletasks()        current_state.window2_open = False        self.newWindow2.destroy()    def button_one(self):        print("button 1 pressed")class SecondWindow:    def __init__(self,master,*args,**kwargs):        #super().__init__(master,*args,**kwargs)        self.mainframe = ttk.Frame(master, padding="5 8 5 5")        self.topframe = ttk.Frame(self.mainframe)        self.button1 = ttk.Button(self.topframe,text="button",command=self.button_function)        self.button1.pack()                        self.topframe.pack(side=tk.TOP, fill=tk.X)        self.mainframe.pack(side=tk.TOP, expand=True, fill=tk.BOTH)    def button_function(self, *event):        print("user just pressed button")    def close_window(self, *event): #Please fix me!        current_state.window2_open = False        self.destroy()class AppStatus:    def __init__(self):        self.window2_open = False  if __name__ == "__main__":     root = tk.Tk()     app = App(root)     current_state = AppStatus()    root.configure(background='grey95')    root.title('Application window')    root.geometry('1000x760+0+0')    root.bind_all("<Mod2-q>", exit)    root.mainloop()