首页 > 解决方案 > Tkinter 列表框中的行为差异,箭头键与鼠标单击

问题描述

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

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

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

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

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

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

方向键

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

鼠标点击

信息“落后”一个,而是显示先前的选择。(如果您再次单击同一项目,它会“赶上”。)

所以我的问题是:

  1. 是什么导致了差异?
  2. 如何修复它以使鼠标单击给出正确的结果?

标签: python-2.7tkintercallbackevent-binding

解决方案


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

您应该能够通过在当前未选择的项目上单击并按住鼠标按钮来看到这一点。当你这样做时,你会看到这样的东西:

在此处输入图像描述

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

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


推荐阅读