Tkinter ttk Treeview binding responds to past events!
Mirko
mirkok.lists at googlemail.com
Mon Sep 11 16:25:45 EDT 2023
Am 11.09.23 um 14:30 schrieb John O'Hagan via Python-list:
> I was surprised that the code below prints 'called' three times.
>
>
> from tkinter import *
> from tkinter.ttk import *
>
> root=Tk()
>
> def callback(*e):
> print('called')
>
> tree = Treeview(root)
> tree.pack()
>
> iid = tree.insert('', 0, text='test')
>
> tree.selection_set(iid)
> tree.selection_remove(iid)
> tree.selection_set(iid)
>
> tree.bind('<<TreeviewSelect>>', callback)
>
> mainloop()
>
> In other words, selection events that occurred _before_ the callback
> function was bound to the Treeview selections are triggering the
> function upon binding. AFAIK, no other tk widget/binding combination
> behaves this way (although I haven't tried all of them).
>
> This was a problem because I wanted to reset the contents of the
> Treeview without triggering a relatively expensive bound function, but
> found that temporarily unbinding didn't prevent the calls.
>
> I've worked around this by using a regular button-click binding for
> selection instead, but I'm curious if anyone can cast any light on
> this.
>
> Cheers
>
> John
AFAIK (it's been quite some time, since I used Tk/Tkinter):
These selection events are not triggered upon binding, but after the
mainloop has startet. Tk's eventloop is queue-driven, so the
tree.selection_{set,remove}() calls just place the events on the
queue. After that, you setup a callback and when the mainloop
starts, it processes the events from the queue, executing the
registered callback.
I seem to remember, that I solved a similar issue by deferring the
callback installation using root.after().
from tkinter import *
from tkinter.ttk import *
root=Tk()
def callback(*e):
print('called')
tree = Treeview(root)
tree.pack()
iid = tree.insert('', 0, text='test')
tree.selection_set(iid)
tree.selection_remove(iid)
tree.selection_set(iid)
root.after(100, lambda: tree.bind('<<TreeviewSelect>>', callback))
mainloop()
This does not print "called" at all after startup (but still selects
the entry), because the callback has not been installed when the
mainloop starts. But any subsequent interaction with the list
(clicking) will print it (since the callback is then setup).
HTH
More information about the Python-list
mailing list