Reputation: 459
from tkinter import *
main = Tk()
var = StringVar()
options = OptionMenu(main, var, 'option1')
options.grid()
options['menu'].add_command(label='option2')
main.mainloop()
When you select 'option1' in the menu it shows that string on the widget. If you select 'option2' it does not show that string on the widget. If you set a command for option2 it will run. Why is 'option2' not showing in the widget when it is selected?
python 3.5
UPDATE:
By adding strings through a for loop I run into a problem where the command for each string uses the same variable.
from tkinter import *
def _print(var, string):
print(string)
var.set(string)
lst = ['hello', 'bob', 'testing']
main = Tk()
var = StringVar()
options = OptionMenu(main, var, 'option1')
options.grid()
for string in lst:
options['menu'].add_command(label=string, command=lambda: _print(var, string))
main.mainloop()
I tried using lambda event, i=string: _print(var, i))
in the loop but lamdba doesnt like it. Says its missing 'event'. I've put event in the _print function and the call to _print but I get the same error that lamdba is missing event. Any idea how I can pass the right variable for each command in the loop?
Upvotes: 0
Views: 4848
Reputation: 8244
It works when you declared 'option2' in the Optionmenu()
widget. More examples can be read from here and here.
from tkinter import *
main = Tk()
var = StringVar()
options = OptionMenu(main, var, 'option1', 'option2')
options.grid()
#options['menu'].add_command(label='option2')
main.mainloop()
I found that the menu
option is used for creating items in a Menu()
widget but not for a Optionmenu()
widget. This is stated here. You can read more about how to declare a .Menu()
widget here. All the best to your tkinter developments.
Edit1:
The reason why it was failing was because you did not declare the command
option associated with the .add_command
method. Having done this alone, you will notice that the Optionmenu
still does not get updated with the new label of the added menu item. To resolve this issue, you have to use the .set()
method of the Control Variable StringVar
to do the updating. See revised script below.
from tkinter import *
def _print1(value):
# By default, callback to OptionMenu has a positional argument for the
# menu item's label.
print(value)
print(var.get())
def _print2():
var.set('option2')
print(var.get())
main = Tk()
var = StringVar()
options = OptionMenu(main, var, 'option1',command=_print1)
options.grid()
options['menu'].add_command(label='option2', command=_print2)
# To add more clickable menu items, the 'add_command' method requires you to
# to declare it's options 'label' and 'command'.
main.mainloop()
Edit2:
command
aspect to options
in Edit1. I
did not address earlier but thought it needed to be shown for
completeness._setit
found in tkinter, which the OptionMenu
widget had used to
do configure the callback used by command
. This approach overcame the issue you encountered.Revised Code:
from tkinter import *
class App(Tk):
def __init__(self, parent=None):
Tk.__init__(self, parent)
self.parent=parent
self.createOM()
self.grid()
def createOM(self):
# Create OptionMenu
omlist=['option1']
self.var = StringVar()
self.options = OptionMenu(self, self.var, *omlist,
command=self._print1)
self.options.grid()
values = ['hello', 'bob', 'testing']
for v in values:
self.options['menu'].add_command(
label=v, command=_setit(self.var, v, self._print2))
# To add more clickable menu items, the 'add_command' method requires you to
# to declare it's options 'label' and 'command'.
def _print1(self, value, *args):
#callback for OptionMenu has these arguments because inherently it
#uses the _setit class to configure the callback with these arguments.
print()
print(value)
#self.var.set('option10') #Uncomment to change OptionMenu display
print(self.var.get())
def _print2(self, value, *args):
print()
print(value)
#self.var.set('option20') #Uncomment to change OptionMenu display
print(self.var.get())
#The following class is extracted from tkinter.
class _setit:
"""Internal class. It wraps the command in the widget OptionMenu."""
def __init__(self, var, value, callback=None):
self.__value = value
self.__var = var
self.__callback = callback
def __call__(self, *args):
self.__var.set(self.__value)
if self.__callback:
self.__callback(self.__value, *args)
if __name__ == "__main__":
app = App()
app.mainloop()
Upvotes: 2
Reputation: 15335
It doesn't select anything because it's not supposed to. You're basically hacking OptionMenu
's visual part. The items you pass as values
are first added to the menu and then are given the command option to modify the selection. When you call options['menu'].add_command(label='option2')
you're basically only modifying the visual part of the widget, 'option2'
is not added to values, and thus command option isn't set. See for yourself in the source code here.
Upvotes: 1