如何在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
相关产品推荐
相关产品推荐

