Reputation: 31
I want to make a feature: when my combobox in tkinter clicked and drop-down menu is opened, when you press any key (for example 's'), it selects first element in combobox, starting with 's' letter. But I cannot find out, how to bind it straight to listBox, which is created by combobox. If I bind keyPress events to combobox, it does not receive events, when drop-down menu opened.
So, I tried stuff like this: self.combobox.bind("<KeyPress>", self.keyPressed)
but no success.
Can you please advice me the way how to do that? Or if it possible at all?
UPDATED: tiny code example
import tkinter as tk
from tkinter import ttk
def pressed(evt):
print ("key pressed")
f = tk.Frame();
f.grid()
c = ttk.Combobox(f,values = ["alfa","betta","gamma"])
c.grid(column = 0, row = 0)
c.bind("<KeyRelease>",pressed)
f.mainloop()
Upvotes: 1
Views: 2877
Reputation: 1
Based on your code, when a key/character is typed (like "s"), the first item starting with the letter in the combobox is selected (if it exists) and if the same key is selected, the next item is selected:
def pressed(event):
widget = event.widget
matching_values = [item for item in widget['values'] if item.lower().startswith(event.char.lower())]
# Select the first matching item if available
if matching_values:
current_value = widget.get()
for i, val in enumerate(matching_values):
if current_value == val:
break
i = 0 if i >= len(matching_values)-1 else i+1
widget.set(matching_values[i]) # Set the combobox to the first match
Upvotes: 0
Reputation: 31
As far as I understood, there no way to get popdown menu in Python currently. And you have to do that through TCL. The weak point is ".f.l" part of reference as it depends on internal widgets implementation. There is an example of combobox, wich will select items by first their letter when you press a keyboard button.
from tkinter import ttk
import itertools as it
class mycombobox(ttk.Combobox):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
pd = self.tk.call('ttk::combobox::PopdownWindow', self) #get popdownWindow reference
lb = pd + '.f.l' #get popdown listbox
self._bind(('bind', lb),"<KeyPress>",self.popup_key_pressed,None)
def popup_key_pressed(self,evt):
values = self.cget("values")
for i in it.chain(range(self.current() + 1,len(values)),range(0,self.current())):
if evt.char.lower() == values[i][0].lower():
self.current(i)
self.icursor(i)
self.tk.eval(evt.widget + ' selection clear 0 end') #clear current selection
self.tk.eval(evt.widget + ' selection set ' + str(i)) #select new element
self.tk.eval(evt.widget + ' see ' + str(i)) #spin combobox popdown for selected element will be visible
return
Upvotes: 2