У меня есть меню, которое при нажатии должно отображать меню, содержащее определенную последовательность строк. Что это за строки в этой последовательности, мы не знаем до времени выполнения, поэтому всплывающее меню должно быть сгенерировано в этот момент. Вот что у меня есть:
class para_frame(Frame):
def __init__(self, para=None, *args, **kwargs):
# ...
# menu button for adding tags that already exist in other para's
self.add_tag_mb = Menubutton(self, text='Add tags...')
# this menu needs to re-create itself every time it's clicked
self.add_tag_menu = Menu(self.add_tag_mb,
tearoff=0,
postcommand = self.build_add_tag_menu)
self.add_tag_mb['menu'] = self.add_tag_menu
# ...
def build_add_tag_menu(self):
self.add_tag_menu.delete(0, END) # clear whatever was in the menu before
all_tags = self.get_article().all_tags()
# we don't want the menu to include tags that already in this para
menu_tags = [tag for tag in all_tags if tag not in self.para.tags]
if menu_tags:
for tag in menu_tags:
def new_command():
self.add_tag(tag)
self.add_tag_menu.add_command(label = tag,
command = new_command)
else:
self.add_tag_menu.add_command(label = "<No tags>")
Важной частью является содержимое в разделе «if menu_tags:» - предположим, что menu_tags - это список ['stack', 'over', 'flow']. Тогда то, что я хочу сделать, это:
self.add_tag_menu.add_command(label = 'stack', command = add_tag_stack)
self.add_tag_menu.add_command(label = 'over', command = add_tag_over)
self.add_tag_menu.add_command(label = 'flow', command = add_tag_flow)
где add_tag_stack () определяется как:
def add_tag_stack():
self.add_tag('stack')
и т. Д.
Проблема в том, что переменная 'tag' принимает значение 'stack', а затем значение 'over' и т. Д., И она не оценивается, пока не будет вызвана команда new_command, после чего переменная 'tag' это просто «поток». Таким образом, добавляемый тег всегда является последним в меню, независимо от того, на что нажимает пользователь.
Первоначально я использовал лямбду, и я подумал, что, возможно, явное определение функции, как указано выше, может работать лучше. В любом случае проблема возникает. Я пытался использовать копию переменной «tag» (либо с «current_tag = tag», либо с помощью модуля copy), но это не решает проблему. Я не уверен почему.
Мой разум начинает блуждать в направлении таких вещей, как «eval», но я надеюсь, что кто-то может придумать умный способ, который не включает в себя такие ужасные вещи.
Большое спасибо!
(В случае необходимости Tkinter .__ version__ возвращает '$ Revision: 67083 $', и я использую Python 2.6.1 в Windows XP.)