tkinter динамическая команда OptionMenu не работает

Я использую python 2.7.9, и моя текущая проблема заключается в том, что по какой-то причине моя команда OptionMenu не работает. Ниже приведен пример кода того, что я имею в виду.

from Tkinter import *

root = Tk()
var = StringVar()
var.set("Choose a name...")
names = []

# Appends names to names list and updates OptionMenu
def createName(n):
    names.append(n)
    personName.delete(0, "end")
    menu = nameMenu['menu']
    menu.delete(0, "end")
    for name in names:
        menu.add_command(label=name, command=lambda name=name: var.set(name))

# what to run when a name is selected
def selection():
    print "Running"  # For testing purposes to see when/if selection runs
    print var.get()

# Option Menu for names
nameMenu = OptionMenu(root, var, (), command=lambda: selection())
nameMenu.grid(row=0, column=0, columnspan=2)
nameMenu.config(width=20)

# Entry for user to submit name
Label(root, text="Name").grid(row=1, column=0)
personName = Entry(root, width=17)
personName.grid(row=1, column=1)

# Add person Button
Button(root, text="Add Person", width=20, command=
       lambda: createName(personName.get())).grid(row=5, column=0, columnspan=2)

mainloop()

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

Теперь мое лучшее предположение о том, что не так, заключается в том, что функция createName(), которую вызывает кнопка, также использует команду OptionMenu из-за строки

menu.add_command(label=name, command=lambda name=name: var.set(name))

Есть ли что-нибудь вокруг этого? Возможно ли, чтобы OptionMenu имел несколько команд?


person Matt_Jacket    schedule 10.04.2015    source источник


Ответы (1)


Вы на правильном пути... Но вместо изменения StringVar вы можете передать имя в свою функцию selection() следующим образом:

from Tkinter import *

root = Tk()

var = StringVar()
var.set("Choose a name...")
names = []

# Appends names to names list and updates OptionMenu
def createName(n):
    names.append(n)
    personName.delete(0, "end")
    menu = nameMenu['menu']
    menu.delete(0, "end")
    for name in names:
        menu.add_command(label=name, command=lambda name=name: selection(name))

# what to run when a name is selected
def selection(name):
    var.set(name)
    print "Running"  # For testing purposes to see when/if selection runs
    print name

# Option Menu for names
nameMenu = OptionMenu(root, var, ())
nameMenu.grid(row=0, column=0, columnspan=2)
nameMenu.config(width=20)

# Entry for user to submit name
Label(root, text="Name").grid(row=1, column=0)
personName = Entry(root, width=17)
personName.grid(row=1, column=1)


# Add person Button
Button(root, text="Add Person", width= 20, command=lambda: createName(personName.get())).grid(row=5, column=0, columnspan=2)


mainloop()
person MrAlexBailey    schedule 10.04.2015
comment
command=lambda name=name: кажется, что выбор(имя) работает, но это довольно запутанно. - person Eric Levieil; 10.04.2015
comment
@EricLevieil Что в этом смущает? Это довольно стандартные вещи, когда дело доходит до вызова функций с аргументами из виджетов Tkinter. - person MrAlexBailey; 10.04.2015
comment
Оно работает! Благодарю вас! Однако я немного смущен тем, как это работает, поскольку в nameMenu = OptionMenu(root, var, (), command=lambda: selection()) selection() не задана переменная. Как работает функция выбора (имя), если переменная не указана? Это просто автоматически дается тем, что выбрано в OptionMenu? - person Matt_Jacket; 10.04.2015
comment
@Matt_Jacket Вы можете изменить эту строку на nameMenu = OptionMenu(root, var, ()) То, что command входит в то, что вызывается, когда вы выбираете пустой раскрывающийся список, прежде чем добавлять имя ... что на самом деле не имеет смысла. - person MrAlexBailey; 10.04.2015
comment
@Jkdc да, это правда, но единственная проблема с этим заключается в том, что когда я запускаю код, добавляю несколько случайных имен и выбираю имя, текст OptionMenu не меняется, когда я делаю выбор. - person Matt_Jacket; 10.04.2015
comment
@Matt_Jacket Добавьте var.set(name) к своей функции selection(). - person MrAlexBailey; 10.04.2015
comment
@Jkdc Спасибо за исправления, теперь все работает отлично! - person Matt_Jacket; 10.04.2015