为何使用postcommand的Tkinter下拉框无法即时联动更新?
问题:Tkinter中Combobox的postcommand无法即时更新第二个下拉框
需求
实现Dropdown1选择后Dropdown2即时更新选项:若Dropdown1选中A,Dropdown2显示“A1, A2”;否则显示“B1, B2”。
我编写的代码(存在问题)
import tkinter as tk from tkinter import ttk class Gui(): def __init__(self): self.root = tk.Tk() self.root.title("GUI") self.root.geometry("300x300") self.frm = tk.Frame(self.root) self.frm.grid(row=0, column=0, sticky="nsew") ttk.Label(self.frm, text="Dropdown1:").grid(row=0, column=0, sticky="w") self.drpDwn1 = ttk.Combobox(self.frm, values=["A", "B"], postcommand=self.reset_flavor) self.drpDwn1.grid(row=0, column=1, sticky="w") ttk.Label(self.frm, text="Dropdown2:").grid(row=1, column=0, sticky="w") self.drpDwn2 = ttk.Combobox(self.frm, values=[""]) self.drpDwn2.grid(row=1, column=1, sticky="w") self.root.mainloop() def reset_flavor(self): value = ["A1", "A2"] if self.drpDwn1.get() == "A" else ["B1", "B2"] self.drpDwn2.configure(values=value) self.drpDwn2.set("") Gui()
问题现象
选中Dropdown1中的A后,Dropdown2的选项仍为“B1, B2”,需再次选中A才会更新为正确选项。
可正常运行的参考代码(来自GitHub Copilot)
import tkinter as tk from tkinter import ttk root = tk.Tk() root.geometry("300x200") dropdown1 = ttk.Combobox(root, width=27, state="readonly") dropdown1['values'] = ("A", "B") dropdown1.grid(row=0, column=0, padx=10, pady=10) dropdown2 = ttk.Combobox(root, width=27, state="readonly") dropdown2.grid(row=1, column=0, padx=10, pady=10) def dropdown1_event(event): if dropdown1.get() == "A": dropdown2['values'] = ("A1", "A2") elif dropdown1.get() == "B": dropdown2['values'] = ("B1", "B2") dropdown1.bind("<<ComboboxSelected>>", dropdown1_event) root.mainloop()
疑问
为何使用postcommand的代码无法正常工作?
原因分析
postcommand是在下拉框的选项列表即将弹出前触发的回调函数,并非在用户选中选项后触发。- 第一次点击Dropdown1选择A时,
postcommand在展开选项列表时执行,此时还未完成选中操作,self.drpDwn1.get()获取的是旧值(初始为空或上一次选中的值),因此Dropdown2被设置为对应旧值的选项。 - 第二次点击Dropdown1选择A时,
postcommand执行时,self.drpDwn1.get()已经是第一次选中的A,所以Dropdown2才会更新为正确选项。
而参考代码中使用的<<ComboboxSelected>>事件,是在用户选中下拉框选项后立即触发的,能准确获取最新选中的值,因此可以即时更新Dropdown2的选项。
修复原代码的方法
保留类结构的前提下,将postcommand替换为绑定<<ComboboxSelected>>事件即可:
- 修改Dropdown1的初始化代码:
self.drpDwn1 = ttk.Combobox(self.frm, values=["A", "B"]) self.drpDwn1.bind("<<ComboboxSelected>>", self.reset_flavor)
- 调整
reset_flavor函数,适配事件回调的参数要求:
def reset_flavor(self, event=None): value = ["A1", "A2"] if self.drpDwn1.get() == "A" else ["B1", "B2"] self.drpDwn2.configure(values=value) self.drpDwn2.set("")
修改后即可实现选中Dropdown1后即时更新Dropdown2的效果。
内容的提问来源于stack exchange,提问作者hrungnir
相关产品推荐
相关产品推荐

