""" ============================================================= Verify that is run on user window closes, but not for still-open windows on a root.quit() (though it _is_ run for still-open windows if mainloop() exits without a quit()). Bind this event on a widget: fires > once if bind on entire window, because nested widgets are destroyed too Typical outout, when run in PyEdit's Run Code and close two: got user close 1 got 1 got user close 3 got 3 [EOF] If the root.quit register line is commented-out: got user close 1 got 1 got user close 3 got 3 got 0 got 2 [EOF] ============================================================= """ from tkinter import * root = Tk() Label(root, text='Root' * 5).pack() def onDestroy(i): print('got ', i) def onClose(i, pop): print('got user close', i) pop.destroy() for i in range(4): pop = Toplevel() lab = Label(pop, text=str(i) * 10) # don't bind to whole window lab.pack() lab.bind('', lambda e, i=i: onDestroy(i)) pop.protocol('WM_DELETE_WINDOW', lambda i=i, pop=pop: onClose(i, pop)) root.protocol('WM_DELETE_WINDOW', root.quit) # run iff this line not run root.mainloop()