JDM
JDM

Reputation: 1804

Behavioral discrepancy in Tkinter listbox, arrow keys vs. mouse click

My environment is Python 2.7, running on Windows 7.

I'm trying get a Tkinter Listbox to trigger a callback in response to the user changing the 'active' item (i.e. the item with focus). I'm using a binding to the <<ListboxSelect>> event to make this happen, and it's working -- sort of.

The callback itself is supposed to check what the new active item is, and carry out some processing accordingly. This logic operates the way I expect when I change the active item via the up/down arrow keys. But when I point & click on a new item instead, the code mistakenly identifies the prior active item as the current one.

Here's a stripped-down code sample that illustrates the behavior I'm getting:

import Tkinter as tk

#Root window
root = tk.Tk()

#Callback to show focus change
def updateDisplay(*args):
    focusIndex = str(lb.index(tk.ACTIVE))
    ctrlFI.set('Focus is at index '+focusIndex)

#Control variables
ctrlLB = tk.StringVar()
ctrlFI = tk.StringVar()

#Widgets
lb  = tk.Listbox(root,
                 width=20, height=10,
                 relief=tk.FLAT,highlightthickness=0,
                 selectmode=tk.EXTENDED,
                 activestyle='dotbox',
                 listvariable=ctrlLB)
lbl = tk.Label(root,
               justify=tk.LEFT, anchor=tk.W,
               textvariable=ctrlFI)
lb.grid(row=0,column=0,sticky=tk.NW,padx=(5,0),pady=5)
lbl.grid(row=1,column=0,columnspan=2,sticky=tk.NW,padx=5,pady=5)

#Listbox binding to trigger callback
lb.bind('<<ListboxSelect>>',updateDisplay)

#Initializations to prep GUI
ctrlLB.set('Index0-entry Index1-entry Index2-entry Index3-entry Index4-entry')
ctrlFI.set('Ready')

#Begin app
tk.mainloop()

Here are the results when you use the arrow keys:

ArrowKeys

But here's what you get when you click with the mouse:

MouseClick

The information 'lags' one behind, showing the prior selection instead. (If you click the same item a second time, it 'catches up.')

So my questions are:

  1. What is causing the discrepancy?
  2. How do I fix it so the mouse click gives the right result?

Upvotes: 2

Views: 1093

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 385900

The active item is not necessarily the same as the selected item. When you press the mouse down it changes the selected value but it does not change the active item. The active item only changes once you release the mouse button.

You should be able to see this by clicking and holding the mouse button over an item that is not currently selected. When you do, you'll see something like this:

enter image description here

In the above image, the active item is the one surrounded by a dotted outline. The selected item is in blue. When your code displays the 'focus', it's displaying the active element rather than the selected element.

If you want the selected item, you need to use curselection to get the index of the selected item. It returns a tuple, so in extended mode you need to get the first element that is returned (eg: lb.curselection()[0]). Be sure to handle the case where curselection returns an empty string.

Upvotes: 2

Related Questions