如何避免 tkinter <<ListboxSelect>>和 .curselection() 检测列表框之外的事件/选择?
问题描述
我正在使用以下 tkinter 小部件:Entry
和 Listbox
.我希望 Entry 小部件在列表框中显示选定的项目 列表框配置为允许 selectmode=tk.SINGLE
.选择由 tkinter 内置的虚拟事件 <<ListboxSelect>>
触发.我的测试脚本如下所示.
I am using the following tkinter widgets: Entry
and Listbox
. I want the Entry widget to display a selected item in the Listbox The Listbox is configured to allow selectmode=tk.SINGLE
. Selection is triggered by tkinter built-in virtual event <<ListboxSelect>>
. My test script is shown below.
条目
在 listbox
选择时被正确更新.但是,在发生 Listbox
选择后,我遇到了以下问题:
Entry
is correctly updated when a Listbox
selection is made. However, I am encountering the following issues after a Listbox
selection has occurred:
- 当鼠标指针在
Entry
中,并且发生Left-Button Double Click
导致选择Entry
中的项目时,抛出 2 个异常. - 如果鼠标指针放在除 tkinter GUI 之外的任何窗口上,例如显示测试脚本的 IDLE 或终端或 ....等,以及当我执行
Left-Button双击
然后在该窗口中选择一个单词,或者当我故意按下鼠标左键
来选择一个段落时,会出现与 1. 中提到的相同的异常.
- When the mousing pointer is in
Entry
, and aLeft-Button Double Click
takes place which leads to selecting the items inEntry
, 2 exceptions is thrown up. - If the mouse pointer is place over any windows other than the tkinter GUI, example over IDLE where the test script is shown or over a terminal or ....etc., and when I do a
Left-Button Double Click
which then selects a word in that window or when I purposely depress theLeft Mouse Button
to select a paragraph, the same exceptions mentioned in 1. appears.
错误如下所示.
注意:当 Listbox
中没有选择时,不会出现上述问题.
Note: The above mentioned issues do not occur when there is no selection made in the Listbox
.
如何避免这两个问题?我怀疑这些问题与 <<ListboxSelect>>
和 widget.curselection()
允许在 Listbox
之外触发但不知道如何进一步调查.
How do I avoid these two issues? I suspect these issues are related to <<ListboxSelect>>
and widget.curselection()
is allowed to be triggered outside of Listbox
the but don't know how to investigate this further.
我想要发生什么?
- 不应注册鼠标指针在其他窗口或不在
Listbox
上的活动. - 在
Entry
中双击不应影响Listbox
中的选择.
- The activities of the mouse pointer when in other windows or not over
Listbox
should not be registered. - Double clicking in
Entry
should not affect the selection in theListbox
.
谢谢.
测试脚本:
import tkinter as tk
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.entrytext = tk.StringVar()
self.entry = tk.Entry(textvariable=self.entrytext)
self.listbox = tk.Listbox(selectmode=tk.SINGLE)
self.entry.pack(side="top", fill="x")
self.listbox.pack(side="top", fill="both", expand=True)
for i in range(100):
self.listbox.insert("end", "item %s" % i)
self.listbox.bind("<<ListboxSelect>>", self.ListboxSelect)
def ListboxSelect(self, event):
widget = event.widget
try:
selection=widget.curselection()
print('
selection = ', selection)
selection_index = int(selection[0])
print('selection_index = ', selection_index)
selection_value = widget.get(selection[0])
print("selection_value = {} ".format(selection_value))
self.entrytext.set(selection_value)
except:
raise
if __name__=='__main__':
a = App()
a.grid()
例外情况:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.5/idlelib/run.py", line 119, in main
seq, request = rpc.request_queue.get(block=True, timeout=0.05)
File "/usr/lib/python3.5/queue.py", line 172, in get
raise Empty
queue.Empty
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/__init__.py", line 1553, in __call__
return self.func(*args)
File "~/entry_listbox_example.py", line 22, in ListboxSelect
selection_index = int(selection[0])
IndexError: tuple index out of range
解决方案
如何避免 tkinter
<<ListboxSelect>>
和.curselection()
检测列表框外的事件/选择?
How to avoid tkinter
<<ListboxSelect>>
and.curselection()
detecting events/selection outside of Listbox?
这完全取决于您的意思.<<ListboxSelect>>
事件被明确设计为在选择更改时触发,无论它如何更改.这可能意味着用户在列表框中选择新的内容,或者从列表框中删除选择时.
That depends on exactly what you mean. The <<ListboxSelect>>
event was explicitly designed to fire whenever the selection changes, no matter how it changes. That could mean when the user selects something new in the listbox, or when the selection is removed from the listbox.
你得到的错误是因为你假设有一个选择,这可能是也可能不是真的.您需要检查选择,并且仅在选择某些内容时运行您的代码.
The errors you get are because you assume that there is a selection, which may or may not be true. You need to check for a selection and only run your code if something is selected.
另一个解决方案,或整体解决方案的一部分,可能是将列表框的 exportselection
选项设置为 False
.当设置为 True
- 默认值 - 任何其他小部件获得选择时,选择将被取消设置.当设置为 False
时,选择不会因为另一个小部件选择了部分或全部数据而改变.
Another solution, or part of the overall solution, might be to set the exportselection
option of the listbox to False
. When set to True
-- the default -- the selection will be unset whenever any other widget gets the selection. When set to False
, the selection won't change just because another widget gets some or all of its data selected.
相关文章