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