Skip to content

Instantly share code, notes, and snippets.

@wasi0013
Created August 25, 2017 20:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wasi0013/c20d8a51d62854320ecfe24ae96b3e58 to your computer and use it in GitHub Desktop.
Save wasi0013/c20d8a51d62854320ecfe24ae96b3e58 to your computer and use it in GitHub Desktop.
Tkinter - Entry with Auto complete Suggestion
import tkinter as tk
import re
"""
This is slight modification of the script: https://gist.github.com/uroshekic/11078820
Changes:
- Fixed value selection
- Added Support for tab or, enter key press to select value
"""
def matches(fieldValue, acListEntry):
pattern = re.compile(re.escape(fieldValue) + '.*', re.IGNORECASE)
return re.match(pattern, acListEntry)
class AutocompleteEntry(tk.Entry):
def __init__(self, autocompleteList, *args, **kwargs):
# Listbox length
if 'listboxLength' in kwargs:
self.listboxLength = kwargs['listboxLength']
del kwargs['listboxLength']
else:
self.listboxLength = 8
# Custom matches function
if 'matchesFunction' in kwargs:
self.matchesFunction = kwargs['matchesFunction']
del kwargs['matchesFunction']
else:
def matches(fieldValue, acListEntry):
pattern = re.compile('.*' + re.escape(fieldValue) + '.*', re.IGNORECASE)
return re.match(pattern, acListEntry)
self.matchesFunction = matches
tk.Entry.__init__(self, *args, **kwargs)
self.autocompleteList = autocompleteList
self.var = self["textvariable"]
if self.var == '':
self.var = self["textvariable"] = tk.StringVar()
self.var.trace('w', self.changed)
self.bind("<right>", self.selection)
self.bind("<up>", self.moveUp)
self.bind("<down>", self.moveDown)
self.bind('<return>',self.selection)
self.bind('<tab>', self.selection)
self.listboxUp = False
def changed(self, name, index, mode):
if self.var.get() == '':
if self.listboxUp:
self.listbox.destroy()
self.listboxUp = False
else:
words = self.comparison()
if words:
if not self.listboxUp:
self.listbox = tk.Listbox(width=25, height=self.listboxLength)
self.listbox.bind("<button-1>", self.selection)
self.listbox.bind("<right>", self.selection)
self.listbox.bind('<return>',self.selection)
self.listbox.bind('<tab>', self.selection)
self.listbox.place(x=self.winfo_x(), y=self.winfo_y() + self.winfo_height())
self.listboxUp = True
self.listbox.delete(0, tk.END)
for w in words:
self.listbox.insert(tk.END,w)
else:
if self.listboxUp:
self.listbox.destroy()
self.listboxUp = False
def selection(self, event):
if self.listboxUp:
self.var.set(self.listbox.get(tk.ACTIVE))
self.listbox.destroy()
self.listboxUp = False
self.icursor(tk.END)
def moveUp(self, event):
if self.listboxUp:
if self.listbox.curselection() == ():
index = '0'
else:
index = self.listbox.curselection()[0]
if index != '0':
self.listbox.selection_clear(first=index)
index = str(int(index) - 1)
self.listbox.see(index) # Scroll!
self.listbox.selection_set(first=index)
self.listbox.activate(index)
def moveDown(self, event):
if self.listboxUp:
if self.listbox.curselection() == ():
index = '0'
else:
index = self.listbox.curselection()[0]
if index != tk.END:
self.listbox.selection_clear(first=index)
index = str(int(index) + 1)
self.listbox.see(index) # Scroll!
self.listbox.selection_set(first=index)
self.listbox.activate(index)
# autocompleteList = [ 'Dora Lyons (7714)', 'Hannah Golden (6010)' ]
# def matches(fieldValue, acListEntry):
# pattern = re.compile(re.escape(fieldValue) + '.*', re.IGNORECASE)
# return re.match(pattern, acListEntry)
# entry = AutocompleteEntry(autocompleteList, root, listboxLength=6, width=25, matchesFunction=matches)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment