Subject: Re: BLT:graph: unexpected behaviour with bind - DN [1]
"George A. Howlett" <gah@cadence.com> - 29 Jun 2000 - comp.lang.tcl
Uwe Klein <uwe-klein@foni.net> wrote:
> if one binds <Destroy> to a toplevel or frame and creates as a child of
> this window
> a blt_graph widget the <Destroy> binding is invoked about 10 times.
> Script for testing:
> graph_bind.tcl {
> package require BLT
> namespace import blt::*
> toplevel .top
> puts "top done"
> bind .top <Destroy> { puts "%W destroy?" }
> puts "bind done"
>
> # ref with frame
> frame .top.frame
> puts "frame done"
> pack .top.frame
> puts "frame pack done"
>
> # test with graph
> graph .top.graph
> puts "graph done"
> pack .top.graph
> puts "pack done"
> }
> Output from this:
> > wish graphtest.tcl
> bind done
> frame done
> frame pack done
> .top.graph.activeLine destroy?
> .top.graph.activeBar destroy?
> .top.graph.x destroy?
> .top.graph.y destroy?
> .top.graph.x2 destroy?
> .top.graph.y2 destroy?
> .top.graph.postscript destroy?
> .top.graph.crosshairs destroy?
> .top.graph.legend destroy?
> .top.graph.grid destroy?
> graph done
> graph pack done
The following is much better explained in Michael McLennan's book
"Effective Tcl/Tk Programming".
When you bind to a toplevel widget (this includes "."), the binding is
set for the toplevel and every each widget in the toplevel. So what
you're seeing are the Destroy events for each widget.
This has to do with the "bindtags" of a widget. When you bind to a
widget, you are actually binding to a "tag", not the widget. A tag is
just a string of characters used to represent a group of widgets.
Every widget has a default set of tags.
% frame .f
.f
% bindtags .f
.f Frame . all
For example a frame ".f" has the following tags
".f" The name of the widget.
"Frame" The class of the widget.
"." The toplevel of the widget.
"all" All widgets.
If you bind to "Frame", you implicitly bind to all frames, since all
frame widgets by default have this tag.
If you bind to "all", you implicitly bind to all widgets, because all
widgets have this tag.
% blt::graph .g
.g
% bindtags .g
.g Graph . all
The third tag is the toplevel that contains the widget. If you bind
to ".", you implicitly bind to every widget in the toplevel. The
purpose is so that you can set keyboard accelerators (short cuts)
with having to bind to every widget in the toplevel explicitly.
bind . <KeyPress-q> { exit 0 }
Now where it gets confusing is when you simply want to bind to a
toplevel widget, but not every widget inside of it. You have
to create a new "bindtag".
% bind destroyWidget <Destroy> { puts "%W destroy?" }
You can then add it to the bindtag list for the widget "."
% bindtags .
. Bltwish all
% bindtags . { destroyWidget . Bltwish all}
Now only "." can trigger this callback.
It's a fairly common mistake. For years, the "Tk Programming FAQ"
offered solutions that had the same problem.
--gah
Last modified
2000-07-20
2000-07-20
(195.108.246.52)
Note: you are looking at
the snapshot of an old wiki
- much of this information
is likely to be very outdated
