Is it possible to make Combobox editable while dropdown is opened? I haven't found any solution. I want to make it more like Google Search but using ComboBox.
Question: Show
Combobox
PopdownWindow, while editing text
This example extends a ttk.Combobox
to the following:
'<Down>'
'<Up'
, if at the first item in the Listbox
Reference:
For each widget, you can bind Python functions and methods to events.
ttk::combobox
— text field with popdown selection list
The
ttk::combobox
uses theentry
andlistbox
widgets internally.
Inherit from ttk.Combox
import tkinter as tk
import tkinter.ttk as ttk
class Combobox(ttk.Combobox):
Helper function, to map the internal Toplevel
and Listbox
to a tkinter
object.
WARNING: This uses
Tk/Tcl
internals, which could change without notice.
This may working only with the tested Tk/Tcl version!
def _tk(self, cls, parent):
obj = cls(parent)
obj.destroy()
if cls is tk.Toplevel:
obj._w = self.tk.call('ttk::combobox::PopdownWindow', self)
else:
obj._w = '{}.{}'.format(parent._w, 'f.l')
return obj
Initalize the object, get the internal references and bind to Key-press events
def __init__(self, parent, **kwargs):
super().__init__(parent, **kwargs)
self.popdown = self._tk(tk.Toplevel, parent)
self.listbox = self._tk(tk.Listbox, self.popdown)
self.bind("<KeyPress>", self.on_keypress, '+')
self.listbox.bind("<Up>", self.on_keypress)
Key-pressed handler to show or hide the PopdownWindow and set the Keyboard focus.
def on_keypress(self, event):
if event.widget == self:
state = self.popdown.state()
if state == 'withdrawn' \
and event.keysym not in ['BackSpace', 'Up']:
self.event_generate('<Button-1>')
self.after(0, self.focus_set)
if event.keysym == 'Down':
self.after(0, self.listbox.focus_set)
else: # self.listbox
curselection = self.listbox.curselection()
if event.keysym == 'Up' and curselection[0] == 0:
self.popdown.withdraw()
Usage:
class App(tk.Tk):
def __init__(self):
super().__init__()
values = ('one', 'two', 'three', 'four', 'five', 'six', 'seven')
self.cb = Combobox(self, value=values)
self.cb.grid(row=0, column=0)
if __name__ == "__main__":
App().mainloop()
Tested with Python: 3.5 - 'TclVersion': 8.6 'TkVersion': 8.6