Tkinter: Distinguishing different
Jeff Epler
jepler at unpythonic.net
Sat Dec 28 13:26:13 EST 2002
On Sat, Dec 28, 2002 at 12:40:07AM +0000, Tim Daneliuk wrote:
> I have an existing program that binds a feature to:
>
> <Control-Double-ButtonRelease3>
>
> I now want to add a new feature which binds to:
>
> <ButtonRelease-3>
>
> The problem is that the handler for the second is always called even
> when I am pressing the key combination for the first. Obviously, the
> "ButtonRelease-2" is checked by the message dispatcher before the
> Control ... combination is checked.
What you describe is in direct conflict with Tk's documentation, or else
you're not describing it clearly enough. Assuming both bindings are made
on the same widget or tag, the more specific binding will be the one used.
So if you have a binding for <X> and <Control-X>, the first binding will
fire for the event <X>, and the event <Alt-X>, and the second binding
will fire for <Control-X> and <Alt-Control-X>.
On the other hand, in the presence of only a binding for <X> on a given
widget/tag, it will fire for all variations of <X>.
If you place one binding on a particular Button, and the other binding on
all Buttons using bind_class(), then two bindings will have the opportunity
to fire. You can return "break" (the string) from a Python binding to stop
this behavior.
I've included the actual documentation from Tk below (a portion of the
manpage bind(n)). This is from version 8.3, but I don't believe the
handling of multiple matching bindings has changed substantially in any
8.x version of Tk.
Jeff
[...]
MULTIPLE MATCHES
It is possible for several bindings to match a given X
event. If the bindings are associated with different
tag's, then each of the bindings will be executed, in
order. By default, a binding for the widget will be exe
cuted first, followed by a class binding, a binding for
its toplevel, and an all binding. The bindtags command
may be used to change this order for a particular window
or to associate additional binding tags with the window.
The continue and break commands may be used inside a bind
ing script to control the processing of matching scripts.
If continue is invoked, then the current binding script is
terminated but Tk will continue processing binding scripts
associated with other tag's. If the break command is
invoked within a binding script, then that script termi
nates and no other scripts will be invoked for the event.
If more than one binding matches a particular event and
they have the same tag, then the most specific binding is
chosen and its script is evaluated. The following tests
are applied, in order, to determine which of several
matching sequences is more specific: (a) an event pattern
that specifies a specific button or key is more specific
than one that doesn't; (b) a longer sequence (in terms of
number of events matched) is more specific than a shorter
sequence; (c) if the modifiers specified in one pattern
are a subset of the modifiers in another pattern, then the
pattern with more modifiers is more specific. (d) a vir
tual event whose physical pattern matches the sequence is
less specific than the same physical pattern that is not
associated with a virtual event. (e) given a sequence
that matches two or more virtual events, one of the vir
tual events will be chosen, but the order is undefined.
If the matching sequences contain more than one event,
then tests (c)-(e) are applied in order from the most
recent event to the least recent event in the sequences.
If these tests fail to determine a winner, then the most
recently registered sequence is the winner.
If there are two (or more) virtual events that are both
triggered by the same sequence, and both of those virtual
events are bound to the same window tag, then only one of
the virtual events will be triggered, and it will be
picked at random:
event add <<Paste>> <Control-y>
event add <<Paste>> <Button-2>
event add <<Scroll>> <Button-2>
bind Entry <<Paste>> {puts Paste}
bind Entry <<Scroll>> {puts Scroll}
If the user types Control-y, the <<Paste>> binding will be
invoked, but if the user presses button 2 then one of
either the <<Paste>> or the <<Scroll>> bindings will be
invoked, but exactly which one gets invoked is undefined.
If an X event does not match any of the existing bindings,
then the event is ignored. An unbound event is not con
sidered to be an error.
MULTI-EVENT SEQUENCES AND IGNORED EVENTS
When a sequence specified in a bind command contains more
than one event pattern, then its script is executed when
ever the recent events (leading up to and including the
current event) match the given sequence. This means, for
example, that if button 1 is clicked repeatedly the
sequence <Double-ButtonPress-1> will match each button
press but the first. If extraneous events that would pre
vent a match occur in the middle of an event sequence then
the extraneous events are ignored unless they are KeyPress
or ButtonPress events. For example, <Double-Button
Press-1> will match a sequence of presses of button 1,
even though there will be ButtonRelease events (and possi
bly Motion events) between the ButtonPress events. Fur
thermore, a KeyPress event may be preceded by any number
of other KeyPress events for modifier keys without the
modifier keys preventing a match. For example, the event
sequence aB will match a press of the a key, a release of
the a key, a press of the Shift key, and a press of the b
key: the press of Shift is ignored because it is a modi
fier key. Finally, if several Motion events occur in a
row, only the last one is used for purposes of matching
binding sequences.
More information about the Python-list
mailing list