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.