Marc Samarra Deumal Marc Samarra Deumal - 4 months ago 13
Python Question

Tkinter: <<ListboxSelect>> event thrown before 'active' item is updated?

So I just came across this issue, and it's been driving me crazy for a couple hours now...
I have a

Listbox
with several items on it. I bind the
<<ListboxSelect>>
event binded to a function called
onSelected
.

This function should print the item that got selected but here's the issue. It prints the last active item rather than the new one.

Here's is an example:
I have 2 items, Item1 and Item2, I select them in the following order:


Item1-Item2-Item1-Item2-Item1


and this is output:


Item1-Item1-Item2-Item1-Item2


Clearly the first one works, but from there it's like the event is thrown before the 'active' item is updated and prints the last 'active' item. Obviously, if i click twice the same item it works as intended.

Is there a workaround for this? I tried waiting for the Listbox to update with
update_idletasks()
, but didn't solve the problem.
What can i do here?

Thanks in advance!

EDIT:

Someone asked for code...:

self.phase = tk.Listbox(self, exportselection = False, selectmode='single')
self.phase.bind('<<ListboxSelect>>', self.onselect)

def onselect(self, evt):
print(self.phase.get('active'))
print(self.phase.select_includes(self.phase.index('active')))


Note that the second print is always False besides the first one.

Answer

The "active" element is not the same as the selection, and it is updated on button release. You are correct that the active element may lag behind the current selection. The selected items are updated on button press. Actually, the updating of the active element on a button click isn't documented, so it may be platform specific. The active element is mostly for navigating the listbox with the keyboard, and isn't particularly relevant when using the mouse.

If you care about getting the item that is selected, use curselection. If you truly care about the active element you'll have to bind to <ButtonRelease> and arrange the bindtags so that your binding happens after the tkinter class binding.

Comments