You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python与Tkinter中判断哪个OptionMenu被选中?

问题描述

开发一款类电子表格程序,某一列的每个单元格都包含一个OptionMenu。每个OptionMenu关联独立的类成员StringVar(存储在数组self.event_option_string_var中),所有OptionMenu共用同一个回调函数,需要判断哪一个OptionMenu(及其关联的StringVar)被选中。

用户代码示例
self.event_option_string_var = []
...

for col in range(HeaderCol.MAX_COL):
    if col == TransactionsGrid.DATE_COL.col:
        widget = DateEntry(self.frame_main, selectmode='day')
        widget.grid(row=1, column=1, padx=0)
        Entry(widget).configure(highlightthickness=0)
    elif col == TransactionsGrid.EVENT_COL.col:
        string_var = StringVar(self.root)
        string_var.set('Select an Event')
        self.event_option_string_var.append(string_var)
        widget = OptionMenu(self.frame_main, string_var,
                            string_var,
                            *TenantEvent.TENANT_EVENTS,
                            command=self.option_changed)

    else:
        widget = Entry(self.frame_main)
        widget.configure(highlightthickness=0)
    button_row.append(widget)
    widget.grid(column=col, row=row + 2, sticky="")

...

def option_changed(self, *args):
    self.event_option_string_var['text'] = f'You selected: {self.event_option_string_var.get()}'
解决方案

核心思路是在创建OptionMenu时,把对应标识(比如行索引、StringVar本身)通过lambda传递给回调函数,直接区分不同的OptionMenu。

方法1:传递行索引和StringVar到回调

修改OptionMenu的创建代码,用lambda包装回调函数,将当前行的索引、对应的StringVar作为参数传入:

elif col == TransactionsGrid.EVENT_COL.col:
    string_var = StringVar(self.root)
    string_var.set('Select an Event')
    self.event_option_string_var.append(string_var)
    # 用lambda传递行索引和当前StringVar
    widget = OptionMenu(self.frame_main, string_var,
                        string_var,
                        *TenantEvent.TENANT_EVENTS,
                        command=lambda val, r=row, var=string_var: self.option_changed(val, r, var))

更新回调函数,接收这些参数:

def option_changed(self, selected_value, row_idx, string_var):
    # row_idx对应表格中的原始行索引,grid显示的是row+2
    grid_row = row_idx + 2
    print(f"第{grid_row}行的OptionMenu选中了: {selected_value}")
    # 直接操作当前OptionMenu的StringVar
    print("当前StringVar的值:", string_var.get())
    # 通过数组查找该StringVar的索引
    var_index = self.event_option_string_var.index(string_var)
    print("该StringVar在数组中的索引:", var_index)

方法2:通过StringVar的trace方法追踪变化

如果不想修改回调参数,也可以给每个StringVar绑定trace方法,当值变化时触发回调并传递自身:

elif col == TransactionsGrid.EVENT_COL.col:
    string_var = StringVar(self.root)
    string_var.set('Select an Event')
    # 绑定trace,值变化时调用回调
    string_var.trace_add('write', lambda *args, var=string_var: self.on_var_change(var))
    self.event_option_string_var.append(string_var)
    widget = OptionMenu(self.frame_main, string_var,
                        string_var,
                        *TenantEvent.TENANT_EVENTS)

对应的回调函数:

def on_var_change(self, string_var):
    selected_value = string_var.get()
    var_index = self.event_option_string_var.index(string_var)
    # 需确保数组顺序和行顺序一致,这里直接用索引对应行
    row_idx = var_index
    print(f"索引{var_index}的StringVar对应行选中了: {selected_value}")

注意事项

  • 原代码中option_changed写法错误:self.event_option_string_var是数组,不能用['text']访问,也不能直接调用get(),必须操作数组中的单个StringVar元素。
  • 使用lambda传递参数时,要把循环变量(比如row)作为默认参数传入,避免捕获循环最后一次的变量值。

内容的提问来源于stack exchange,提问作者jordanthompson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 23:48:30