Cómo actualizar el comando de un OptionMenu

Estoy tratando de establecer o actualizar el comando de un menú de opciones después de su instanciación.

La widget.configure(command=foo) funciona para Button y CheckButton , pero no para OptionMenu .

El siguiente código genera este error: _tkinter.TclError: unknown option "-command"

 from Tkinter import Tk, OptionMenu, StringVar root = Tk() var = StringVar() def foo(val): print val, var.get() widget = OptionMenu(root, var, "one", 'two') widget.configure(command=foo) widget.pack() root.mainloop() 

Creo que lo que realmente estás preguntando es cómo asociar un comando a un Optionmenu , en lugar de actualizar un comando (no hay un comando, así que no hay nada que actualizar).

Si desea que se llame a una función cada vez que se seleccione un valor en un Optionmenu , puede agregar un rastreo en la variable relacionada. La traza llamará a una función cuando esa variable cambie, ya sea a través del Optionmenu o por cualquier otro medio.

Por ejemplo:

 ... var = tk.StringVar() def foo(*args): print "the value changed...", var.get() var.trace("w", foo) ... 

Cuando se llama a la función, se pasarán tres argumentos, que puede ignorar de forma segura en este caso.

Para obtener más información sobre las trazas de variables, visite http://effbot.org/tkinterbook/variable.htm


También es posible que desee considerar cambiar al cuadro combinado ttk . Admite la vinculación a <> , que es un poco menos torpe que hacer una traza variable.

¡Buena pregunta! Es bueno que nunca haya tenido que hacer esto en ninguno de mis proyectos antes porque (a menos que alguien demuestre que estoy equivocado) no puede configurar / actualizar el comando de un widget OptionMenu una vez que ya esté definido.

Si Tkinter quisiera que pudieras hacer eso, definitivamente lo habría incluido para ser editado por .configure()

Hay una función práctica llamada .keys() que puede llamar con un objeto de widget para ver todos los rasgos disponibles que se pueden usar con .configure() .

Ejemplo de botón:

 from tkinter import * master = Tk() def callback(): print ("click!") b = Button(master, text="OK", command=callback) print (b.keys()) #Printing .keys() b.pack() mainloop() 

Lo que resulta en : introduzca la descripción de la imagen aquí

Observe cómo en esta enorme lista de claves, 'command' está en la segunda línea? Esto se debe a que el command un botón se puede usar en .configure()

Ejemplo de OptionMenu:

 from tkinter import * root = Tk() var = StringVar() def foo(val): print ("HI") widget = OptionMenu(root, var, "one", 'two') print(widget.keys()) widget.pack() root.mainloop() 

Lo que resulta en: introduzca la descripción de la imagen aquí

Observe que no hay un 'command' en la línea 2 esta vez. Esto se debe a que no puede configurar el command con un widget OptionMenu.

¡Espero que este problema no obstaculice demasiado su progtwig y espero que mi respuesta le haya ayudado a comprender mejor!

Es posible cambiar los comandos asociados con los widgets OptionMenu si tiene cuidado (como comentó @Bryan Oakley). A continuación se muestra un ejemplo de hacerlo.

La parte difícil es que tienes que reconfigurar todos los elementos del menú, no solo uno de ellos. Esto requiere un poco de contabilidad adicional (y algunos gastos generales de procesamiento, pero es imperceptible).

Inicialmente, el menú tiene tres elementos, cada uno con una función diferente a la que se debe llamar cuando se selecciona, uno de los cuales cambia el menú. Si se selecciona este último, el menú se cambia para que solo tenga dos elementos del menú, los cuales llaman a la misma función.

 from tkinter import * root = Tk() var = StringVar() var.set('Select') def foo(value): var.set(value) print("foo1" + value) def foo2(value): var.set(value) print("foo2 " + value) def foo3(value): var.set(value) print("foo3 " + value) def change_menu(value): var.set('Select') print('changing optionmenu commands') populate_menu(optionmenu, one=foo3, two=foo3) def populate_menu(optionmenu, **cmds): menu = optionmenu['menu'] menu.delete(0, "end") for name, func in cmds.items(): menu.add_command(label=name, command= lambda name=name, func=func: func(name)) optionmenu = OptionMenu(root, var, ()) # no choices supplied here optionmenu.pack() Label(root, textvariable=var).pack() populate_menu(optionmenu, one=foo, two=foo2, change=change_menu) root.mainloop()