I have a function that creates a ttk combo box
def cb(x, sql_query, Var):
global comboBox
from tkinter import ttk
textfont = ("Helvetica", 14)
comboBox = ttk.Combobox(x, font=textfont, width=15, textvariable=Var)
comboBox.pack(anchor='e', pady=5)
update(sql_query)
# update items in list based on a sql query
def update(sql_query):
lis = []
lis.clear()
def query(*args, **kwargs):
nonlocal sql_query
import sqlite3
mydb = sqlite3.connect('Assets/backend/Data.db')
cursor = mydb.cursor()
cursor.execute(sql_query)
a = cursor.fetchall()
for i in a:
lis.append(i)
mydb.commit()
mydb.close()
query(lis)
comboBox['values'] = lis
now if I have a combo box for user to add/fetch items from, he'd start typing Burger for example. If burger is in items table it will be already appended to the list setting the values for the combo box and this works just fine. the part I can't achieve here is to set auto complete so when the user start typing if the item exist it will be auto completed. I have found a code but I can't modify it to my scenario I'm not good with classes still
from tkinter import *
import sqlite3
from tkinter import ttk
class AutocompleteCombobox(ttk.Combobox):
def set_completion_list(self, completion_list):
"""Use our completion list as our drop down selection menu, arrows move through menu."""
self._completion_list = sorted(completion_list, key=str.lower) # Work with a sorted list
self._hits = []
self._hit_index = 0
self.position = 0
self.bind('<KeyRelease>', self.handle_keyrelease)
self['values'] = self._completion_list # Setup our popup menu
def autocomplete(self, delta=0):
"""autocomplete the Combobox, delta may be 0/1/-1 to cycle through possible hits"""
if delta: # need to delete selection otherwise we would fix the current position
self.delete(self.position, END)
else: # set position to end so selection starts where textentry ended
self.position = len(self.get())
# collect hits
_hits = []
for element in self._completion_list:
if element.lower().startswith(self.get().lower()): # Match case insensitively
_hits.append(element)
# if we have a new hit list, keep this in mind
if _hits != self._hits:
self._hit_index = 0
self._hits=_hits
# only allow cycling if we are in a known hit list
if _hits == self._hits and self._hits:
self._hit_index = (self._hit_index + delta) % len(self._hits)
# now finally perform the auto completion
if self._hits:
self.delete(0,END)
self.insert(0,self._hits[self._hit_index])
self.select_range(self.position,END)
def handle_keyrelease(self, event):
"""event handler for the keyrelease event on this widget"""
if event.keysym == "BackSpace":
self.delete(self.index(INSERT), END)
self.position = self.index(END)
if event.keysym == "Left":
if self.position < self.index(END): # delete the selection
self.delete(self.position, END)
else:
self.position = self.position-1 # delete one character
self.delete(self.position, END)
if event.keysym == "Right":
self.position = self.index(END) # go to end (no selection)
if len(event.keysym) == 1:
self.autocomplete()
# No need for up/down, we'll jump to the popup
# list at the position of the autocompletion
def test(test_list):
"""Run a mini application to test the AutocompleteEntry Widget."""
root = Tk(className='AutocompleteCombobox')
combo = AutocompleteCombobox(root)
combo.set_completion_list(test_list)
combo.pack()
combo.focus_set()
# I used a tiling WM with no controls, added a shortcut to quit
root.bind('<Control-Q>', lambda event=None: root.destroy())
root.bind('<Control-q>', lambda event=None: root.destroy())
root.mainloop()
if __name__ == '__main__':
test_list = ('apple', 'banana', 'Cranberry', 'dogwood', 'alpha', 'Acorn', 'Anise', 'Strawberry' )
test(test_list)
I want to edit that to include my functions instead of the giving example, thanks in advance.