Reputation: 8234
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.
Entry
is correctly updated when a Listbox
selection is made. However, I am encountering the following issues after a Listbox
selection has occurred:
Entry
, and a Left-Button Double Click
takes place which leads to selecting the items in Entry
, 2 exceptions is thrown up.Left-Button Double Click
which then selects a word in that window or when I purposely depress the Left Mouse Button
to select a paragraph, the same exceptions mentioned in 1. appears.The errors are shown below.
Note: The above mentioned issues do not occur when there is no selection made in the 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.
What I want to happen?
Listbox
should not be registered.Entry
should not affect the selection in the Listbox
. Thank you.
Test Script:
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('\nselection = ', 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()
Exceptions:
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
Upvotes: 3
Views: 4691
Reputation: 385890
How to avoid tkinter
<<ListboxSelect>>
and.curselection()
detecting events/selection outside of Listbox?
That depends on exactly what you mean. The <<ListboxSelect>>
event was explicitly designed to fire whenever the selection in the listbox 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.
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.
Upvotes: 4