我有一個menubutton,點擊時會顯示一個包含特定字符串序列的菜單。到底什麼是字符串,我們直到運行時才知道,所以彈出的菜單必須在那一刻生成。下面是我有:在Tkinter中動態創建菜單。 (lambda表達式?)
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>")
的重要組成部分,是下的東西,「如果menu_tags:」 - 假設menu_tags是列表[「堆」,「過」,「流」。那麼我想這樣做有效的是這樣的:
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 '只是'流'。因此,添加的標籤始終是菜單上的最後一個,無論用戶點擊了什麼。
我最初使用lambda,我想也許明確定義這個函數可能會更好。無論哪種方式發生問題。我試過使用變量'tag'的副本(或者使用「current_tag = tag」或者使用複製模塊),但這並不能解決問題。我不知道爲什麼。
我的思想開始徘徊在諸如「eval」之類的東西上,但我希望有人能夠想到一種不涉及這種可怕事情的聰明方式。
非常感謝!
(如果它是相關的,Tkinter的.__ version__返回 '$修訂:67083 $',我使用Python 2.6.1在Windows XP上。)
我不知道爲什麼這個工程,但它呢!儘管我喜歡其他答案的詳細解釋,但我會使用這個,因爲它稍微短一些。謝謝! – MatrixFrog 2009-04-08 06:49:03
我認爲它的工作原因是函數參數列表中的tag = tag默認參數。這樣做會在函數範圍內創建名稱'tag',指向調用者範圍內的值標記。 如果我錯了,請糾正我,我目前正在處理類似的範圍問題。 – 2009-05-19 06:46:38