1
votes

I am wondering if this is possible...?

Imagine a tkinter app with an entry box widget for entering a PC name. As soon as the user starts typing in the box, the app will show the possible names based on what you type, so the more you type the fewer options you see until you are only left with one, or a small-enough selection to click on it from the available options.

If this is possible in tkinter, if someone could point me in the direction of a simple example(s), that'd be great!

I can't post any sample code, as this is a general rather than specific question.

1
Yes, that's possible. Which part are you stuck on? - jonrsharpe
Thanks @jonrsharpe! I'm still pretty much a rookie at all this, I can do a basic text entry box of course, but making it dynamic - not sure where to start... - user3514446
Look at bindings. You need to bind to <Key> and then run whatever code is needed to show the options. - anderswb
@anderswb: binding to <Key> isn't the only solution, it's just a solution. - Bryan Oakley
@BryanOakley: Hence I didn't put it as an answer. I'm pretty new at tkinter, as you might have gathered from some of my other answers. I like your trace solution! - anderswb

1 Answers

6
votes

You can associate an instance of StringVar with the entry widget, and then put a trace on that instance to call a callback when the value changes. You can then do whatever you want in that callback -- update a list, pop up a window, etc.

Here's an example that simply filters the list based on what you type.

import Tkinter as tk

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        self.choices = ("one", "two", "three", "four", "five", 
                        "six", "seven", "eight", "nine", "ten",
                        "eleven", "twelve", "thirteen", "fourteen",
                        "fifteen", "sixteen", "seventeen", "eighteen",
                        "nineteen", "twenty")

        self.entryVar = tk.StringVar()
        self.entry = tk.Entry(self, textvariable=self.entryVar)
        self.listbox = tk.Listbox(self)
        self.listbox.insert("end", *self.choices)

        self.entry.pack(side="top", fill="x")
        self.listbox.pack(side="top", fill="both", expand=True)

        self.entryVar.trace("w", self.show_choices)
        self.listbox.bind("<<ListboxSelect>>", self.on_listbox_select)

    def on_listbox_select(self, event):
        """Set the value based on the item that was clicked"""
        index = self.listbox.curselection()[0]
        data = self.listbox.get(index)
        self.entryVar.set(data)

    def show_choices(self, name1, name2, op):
        """Filter choices based on what was typed in the entry"""
        pattern = self.entryVar.get()
        choices = [x for x in self.choices if x.startswith(pattern)]
        self.listbox.delete(0, "end")
        self.listbox.insert("end", *choices)

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()