Tkinter - tracking toplevel windows

Jeff Epler jepler at unpythonic.net
Mon Apr 7 21:37:32 CEST 2003


On Mon, Apr 07, 2003 at 11:23:13AM -0700, Andrew Wheatley wrote:
> I have a Tkinter Gui with a button which generates other toplevel windows.
> Whenever a toplevel is generated, I append its id to a global list.  What I'd like
> to do with wm_protocol/WM_DELETE_WINDOW method is remove from the list
> the window id currently being killed and then destroy the window.
> 
> My question is:
> 
> How can I tell which window is being destroy when I kill it with the X in the 
> top right hand corner.

Arrange to include a reference to the window when in the callback.  For
example:

    def close_clicked(t):
        print "close was clicked on window", t

    t = Tkinter.Toplevel()
    t.wm_protocol('WM_DELETE_WINDOW', lambda t=t: close_clicked())

When WM_DELETE_WINDOW is defined, using window-manager "close"
functionality (such as ALT-F4, clicking the "X", etc) merely triggers
the callback, which can override the close event.

There's also the <Destroy> binding, but this is a little more
problematic.  You *can* use the .widget attribute of the event, but due
to a detail of Tk internals*, this binding will be applied to any widget
inside t.  So below, you'll get two messages:

    def destroyed(evt):
        print "window", evt.widget, "was destroyed"

    t.bind("<Destroy>", destroyed)
    b = Tkinter.button(t); b.pack()
    t.destroy()

So if you're interested only in toplevel windows, do this:
    def destroyed_smarter(evt):
        if not evt.widget.wm_toplevel() is evt.widget:
            return # not actually the window
        print "window", evt.widget, "was destroyed"

The <Destroy> event fires after the destruction has begun, so there's no
opportunity to veto the destruction.

Jeff
* See the documentation on "bindtags" for an explanation of why this is
  so





More information about the Python-list mailing list