Federico Dorato
Federico Dorato

Reputation: 784

Tkinter - Selecting an item from a Treeview using single click instead of double click (Callback on Treeview item selection)

When you want to select an item in a Treeview, you usually use the double-click:

def print_element(event):
    print(my_treeview.selection()[0])
my_treeview.bind("<Double-1>", print_element)

Today I tried to do the same but using a single click instead:

my_treeview.bind("<Button-1>", print_element)

But it wouldn't work. The output was just an empty tuple. I started to search online for an explanation... why is it not working?

EDIT: My goal was actually to do something every time a treeview item was selected.

Upvotes: 2

Views: 7827

Answers (3)

Bryan Oakley
Bryan Oakley

Reputation: 385830

The reason it doesn't work the way you expect is because your custom single-click binding happens before the default behavior. So, when your single-click is processed, that happens before an item is selected. The second time you click, your function will print the previously selected item.

If you want to have a function called when an item is selected, you should bind to <<TreeviewSelect>>, which will fire immediately after the user selects an item with a single click or via the keyboard.

The default behavior of a treeview supports selecting multiple items at once, so the following code will print out the text of all of the selected items as a list, even if only a single item is selected. You can, of course, modify this to only print out the first selected item if you so desire.

def print_element(event):
    tree = event.widget
    selection = [tree.item(item)["text"] for item in tree.selection()]
    print("selected items:", selection)

tree.bind("<<TreeviewSelect>>", print_element)

Upvotes: 5

acw1668
acw1668

Reputation: 46669

It is because the selection is not set yet when the <Button-1> (it is the same as <ButtonPress-1>, i.e. when the mouse button 1 is pressed and not released) event callback is called.

You should bind on <ButtonRelease-1> or <<TreeviewSelect>> instead as the selection is set when the event callback is being executed.

Upvotes: 1

Federico Dorato
Federico Dorato

Reputation: 784

Why it doesn't work

When you click an item in a treeview, that item is still not in a SELECTED status in the moment the callback is activated. You are changing the status in that very moment.

Using a double-click, the first click change the status, and at the second click you are activating your callback, so the status has already been changed.

How can it work

Kudos to this website

In short,

def print_element(event):
    print(my_treeview.identify('item', e.x, e.y))
my_treeview.bind("<Button-1>", print_element)

This time, print_element() will check the coordinates of the mouse, and will discover the selected item check what is under the mouse. Nice and clean!

Upvotes: 0

Related Questions