Как обновить команду OptionMenu

Я пытаюсь установить или обновить команду OptionMenu после ее создания.

widget.configure(command=foo) заявление работает для Button а также CheckButton, но не для OptionMenu,

Следующий код вызывает эту ошибку: _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()

3 ответа

Решение

Я думаю, что вы действительно спрашиваете, как связать команду с Optionmenuвместо обновления команды (команды нет, поэтому обновлять нечего).

Если вы хотите, чтобы функция вызывалась каждый раз, когда значение выбирается из Optionmenu, вы можете добавить след на связанной переменной. Трассировка будет вызывать функцию всякий раз, когда эта переменная изменяется, будь то через Optionmenu или любым другим способом.

Например:

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

Когда функция вызывается, она передает три аргумента, которые в этом случае можно смело игнорировать.

Для получения дополнительной информации о переменных трассировки см. http://effbot.org/tkinterbook/variable.htm


Вы также можете рассмотреть возможность перехода к списку ttk. Поддерживает привязку к <<ComboboxSelected>>, что немного менее неуклюже, чем делать переменную трассировку.

Хороший вопрос! Хорошо, что мне никогда раньше не приходилось делать это ни в одном из моих проектов, потому что (если здесь кто-то не докажет, что я не прав)вы не можете установить / обновить команду виджета OptionMenu, когда он уже определен.

Если бы Tkinter хотел, чтобы вы могли это сделать, он определенно включил бы его для редактирования .configure()

Есть удобная функция под названием .keys() который вы можете вызвать с помощью объекта виджета, чтобы увидеть все доступные черты, которые могут быть использованы с .configure(),

Пример кнопки:

from tkinter import *

master = Tk()

def callback():
    print ("click!")

b = Button(master, text="OK", command=callback)
print (b.keys()) #Printing .keys()
b.pack()

mainloop()

Что приводит к:

Обратите внимание, как в этом огромном списке ключей, 'command' на второй линии? Это потому, что кнопки command МОЖЕТ использоваться в .configure()

Пример 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()

Что приводит к:

Обратите внимание, как нет 'command' на линии 2 на этот раз. Это потому, что вы не можете настроить command с виджетом OptionMenu.

Надеюсь, эта проблема не слишком мешает вашей программе, и я надеюсь, что мой ответ помог вам лучше понять!

Можно изменить команды, связанные с расширением OptionMenu, если вы будете осторожны (как прокомментировал @Bryan Oakley). Ниже приведен пример этого.

Сложность в том, что вам нужно перенастроить все пункты меню, а не только один из них. Это требует некоторой дополнительной бухгалтерии (и некоторых накладных расходов на обработку, но это незаметно).

Изначально меню состоит из трех пунктов, каждый из которых имеет свою функцию, которая вызывается при выборе, один из которых меняет меню. Если последний выбран, меню изменяется, чтобы иметь только два пункта меню, каждый из которых вызывает одну и ту же функцию.

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()
Другие вопросы по тегам