クリックすると、特定の文字列シーケンスを含むメニューが表示されるメニューボタンがあります。そのシーケンスに正確にどのような文字列があるかは実行時までわからないため、ポップアップするメニューはその時点で生成する必要があります。ここに私が持っているものがあります:
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' のコピーを使用してみましたが (「current_tag = tag」または copy モジュールを使用)、解決しません。理由はわかりません。
私の心は「eval」のようなものに向かってさまよい始めていますが、誰かがそのような恐ろしいことを伴わない賢い方法を考えてくれることを願っています.
どうもありがとう!
(関連がある場合、Tkinter.__version__ は '$Revision: 67083 $' を返します。私は Windows XP で Python 2.6.1 を使用しています。)