MGS [2003/09/20] - Sometimes it is necessary/desirable to bind to a toplevel window. For example, I might want to withdraw a toplevel window, instead of having it iconify, when clicking the minimize button. There are several ways to do this:
1. Bind directly to the window name. e.g.
bind . <Unmap> [list wm withdraw .]
However, the binding will trigger if you decide to unmanage any of the window's child widgets, due to their default binding tags.
2. Bind to the toplevel window's class. e.g.
bind [winfo class .] <Unmap> [list wm withdraw %W]
However, this binding will fire for all windows with the same class as . .
3. Create a new binding tag for the toplevel window and then create the binding to that tag. e.g.
bindtags . [list . bind. [winfo class .] all] bind bind. <Unmap> [list wm withdraw %W]
or more generally:
set W [toplevel .mywin] bindtags $W [linsert [bindtags $W] 1 bind$W] bind bind$W <Unmap> [list wm withdraw %W]
RUJ: Hi, I would like to know ... How to bind a "Leave" command to main toplevel but it should be work on its child widgets also. I want to make popupwindow which will have some entries and labels & this window should destroyed after cursor moved away from window.
MJ - Just destroy the toplevel and all its child widgets are destroyed as well. In the <Leave> event binding make sure you only call the destroy when the toplevel is closed. Leaving a child widget will also call the binding, because the toplevel is in every child widget's bindtags list.
toplevel .l bind .l <Leave> {tlclose %W} proc tlclose {w} {if {$w == [winfo toplevel $w]} {destroy $w}}
RUJ: Thanking you it is working very well. Before that i was trying by,
set destroyScript [list destroy $wa] bind $wa <Enter> [list after cancel $destroyScript] bind $wa <Leave> $destroyScript
RUJ: hello MJ, I am trying to use above code for dragging window but it not working. this is the code giving error of expression syntax.
set ::moveable 0 wm overrideredirect $wa 1 bind $wa <ButtonPress> {set ::moveable 1} bind $wa <ButtonRelease> {set ::moveable 0} bind $wa <Motion> {if {!$::moveable} {break}; if {%W == [winfo toplevel %W]} {wm geometry [winfo toplevel %W] +[expr %X-5]+[expr %Y-5]} }
The first part of the solution is to move all that code to a proc. Unless you have a specific reason to do otherwise you should stick to the rule of thumb "never have more than one command in a binding". It makes writing and maintaining code like this soooo much easier.
Try this:
bind $wa <Motion> [list handleMotionEvent %W %X %Y] proc handleMotionEvent {w x y} { if {! $::moveable} return set top [winfo toplevel $w] if {$w ne $top} return wm geometry $top +[expr {$x-5}]+[expr {$y-5}] }
See also: