Getting the choice of optionmenu right after selection Python Getting the choice of optionmenu right after selection Python tkinter tkinter

Getting the choice of optionmenu right after selection Python


Trace the StringVar.

from Tkinter import *def option_changed(*args):    print "the user chose the value {}".format(variable.get())    print amaster = Tk()a = "Foo"variable = StringVar(master)variable.set("Apple") # default valuevariable.trace("w", option_changed)w = OptionMenu(master, variable, "Apple", "Orange", "Grapes")w.pack()mainloop()

Here, option_changed will be called whenever the user chooses an option from the option menu.


You can wrap the trace argument in a lambda to specify your own parameters.

def option_changed(foo, bar, baz):    #do stuff#...variable.trace("w", lambda *args: option_changed(qux, 23, "hello"))


When I come across widgets with annoying interfaces - such as OptionMenu, I generally will write a class around it to abstract away the annoying attributes. In this case, I really dislike the verbosity of using the StringVar every time I want to create a dropdown, so I simply created a DropDown class which includes the StringVar within the class (written in Python 3.5, but translates easily to all):

class DropDown(tk.OptionMenu):    """    Classic drop down entry    Example use:        # create the dropdown and grid        dd = DropDown(root, ['one', 'two', 'three'])        dd.grid()        # define a callback function that retrieves the currently selected option        def callback():            print(dd.get())        # add the callback function to the dropdown        dd.add_callback(callback)    """    def __init__(self, parent, options: list, initial_value: str=None):        """        Constructor for drop down entry        :param parent: the tk parent frame        :param options: a list containing the drop down options        :param initial_value: the initial value of the dropdown        """        self.var = tk.StringVar(parent)        self.var.set(initial_value if initial_value else options[0])        self.option_menu = tk.OptionMenu.__init__(self, parent, self.var, *options)        self.callback = None    def add_callback(self, callback: callable):        """        Add a callback on change        :param callback: callable function        :return:         """        def internal_callback(*args):            callback()        self.var.trace("w", internal_callback)    def get(self):        """        Retrieve the value of the dropdown        :return:         """        return self.var.get()    def set(self, value: str):        """        Set the value of the dropdown        :param value: a string representing the        :return:         """        self.var.set(value)

Example usage:

# create the dropdown and grid, this is the ONLY required codedd = DropDown(root, ['one', 'two', 'three'])dd.grid()# optionally, define a callback function that retrieves the currently selected option then add that callback to the dropdowndef callback():    print(dd.get())dd.add_callback(callback)

Edited to add: Not long after creating this post, I got annoyed with a few other attributes of tk and ended up creating a package called tk_tools to make dropdowns and checkbuttons easier along with addressing other annoyances.