python gui events out of order

This is how bindings work (and that’s a good thing), but your problem is easily solved.

Bindings are fired in the order specified by a widgets binding tags (also known as bind tags or bindtags). Unless you specify otherwise, the bindings happen in the following order:

  1. if there is a binding directly on the widget it will be fired before any other bindings.
  2. if there is a binding on the widget’s class, it is fired next
  3. if there is a binding on the toplevel widget that contains the widget, it is fired next (note: the root window is considered a toplevel window in this context)
  4. if there is a binding on “all” it will fire next.

The sequence can be stopped at any point by one of the event handlers, but that’s beside the point for this specific discussion.

In the default case, your binding on <Key> happens before the class binding, and it is the class binding where the text is actually inserted into the widget. That is why your binding always seems to be one character behind.

Normally this order of things is exactly right, since more specific bindings get a chance to override the default behavior. If it wasn’t this way you’d always get the default behavior even if you didn’t want it. One place where this is not always what you want is when you want to augment the default bindings rather than replace them.

You can swap the order of the bindtags so that the class binding happens first. Or, add an additional bindtag to your text widget and add that in the sequence after the class binding, and bind to that. Usually adding a bindtag is the better solution, but not always.

To change the bindtags you can do something like this:

self.inputText.bindtags(((str(self.inputText)), "Text", "post-insert", ".", "all"))

To bind to “post-insert”, do it with the bind_class method:

self.inputText.bind_class("post-insert", "<Key>", self.translate)

It may seem odd, but bindtags are one of the most powerful binding mechanisms out there. They give you complete and total control over the order of bindings, which is much more difficult with any other toolkit.

By the way, don’t forget that if you get all the characters to the end of the text widget there will always be an extra newline at the end. Either get to end-1c, or trim off one newline from the text.

Leave a Comment