Tkinter 列表框中的行为差异,箭头键与鼠标单击

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

我的环境是 Python 2.7,运行 在 Windows 7.

我正在尝试让 Tkinter 列表框触发回调以响应用户更改 'active' 项目(即具有焦点的项目)。我正在使用绑定到 <<ListboxSelect>> 事件来实现这一点,并且它正在工作 - 有点。

回调本身应该检查新的活动项目是什么,并相应地进行一些处理。当我通过 up/down 箭头键更改活动项目时,此逻辑按照我期望的方式运行。但是,当我指向并单击一个新项目时,代码错误地将先前的活动项目识别为当前项目。

这是一个精简的代码示例,它说明了我得到的行为:

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()

以下是使用箭头键时的结果:

但是当你用鼠标点击时你得到的是:

信息'lags'落后一位,改为显示先前的选择。 (如果你再次点击同一个项目,它 'catches up.')

所以我的问题是:

  1. 造成差异的原因是什么?
  2. 我该如何修复它才能使鼠标点击得到正确的结果?

活动项目不一定与所选项目相同。当您按下鼠标时,它会更改所选值 但不会更改活动项目 。活动项目只有在您释放鼠标按钮后才会更改。

您应该可以通过在当前未选中的项目上单击并按住鼠标按钮来看到它。当你这样做时,你会看到类似这样的东西:

在上图中,活动项目是被虚线包围的项目。所选项目为蓝色。当您的代码显示 'focus' 时,它显示的是活动元素而不是所选元素。

如果你想要选中的项目,你需要使用curselection来获取选中项目的索引。它 returns 是一个元组,因此在扩展模式下您需要获取返回的第一个元素(例如:lb.curselection()[0])。请务必处理 curselection returns 空字符串的情况。