0

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.

rizerphe
  • 1,340
  • 1
  • 14
  • 24
  • You seem to have posted more code than what would be reasonable for your issue. Please read [ask] and how to make a [mre]; providing a MRE helps users answer your question and future users relate to your issue. – rizerphe Jun 19 '20 at 15:29
  • Does this answer your question? [tkinter-how-to-create-a-combo-box-with-autocompletion](https://stackoverflow.com/questions/12298159) – stovfl Jun 19 '20 at 16:20

0 Answers0