如何让for循环生成的ttk Combobox实现逐行独立联动更新值
实现每行品牌与车型下拉框独立联动的方案
问题根因
- 循环创建控件时,反复将品牌、车型下拉框赋值给
self的同名属性,循环结束后self.make_selection和self.model_selection只会保留最后一行的控件实例,更新操作自然只会作用在最后一行。 - 事件绑定用到的
lambda存在迟绑定特性,触发事件时取到的变量是循环结束后的最终值,永远指向最后一行的控件。
修正思路
不使用实例属性存储每行控件,通过lambda默认参数保存当前循环的车型下拉框实例,调整更新方法直接操作传入的当前行控件即可,保证每行的联动关系独立。
修正后完整可运行代码
import tkinter as tk from tkinter import font as tkfont, filedialog, messagebox from tkinter.ttk import Combobox class SLS_v1(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) # Setting up the root window self.title('Test App') self.geometry("200x300") self.resizable(False, False) self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic") container = tk.Frame(self) container.pack(side="top", fill="both", expand=True) container.grid_rowconfigure(0, weight=1) container.grid_columnconfigure(0, weight=1) self.frames = {} self.frames["MenuPage"] = MenuPage(parent=container, controller=self) self.frames["template"] = template(parent=container, controller=self) self.frames["MenuPage"].grid(row=0, column=0, sticky="nsew") self.frames["template"].grid(row=0, column=0, sticky="nsew") self.show_frame("MenuPage") def show_frame(self, page_name): frame = self.frames[page_name] frame.tkraise() class MenuPage(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller template = tk.Button(self, text='Template', height=3, width=20, bg='white', font=('12'), command=lambda: controller.show_frame('template')) template.pack(pady=50) class template(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller self.grid(columnspan=10, rowspan=10) button = tk.Button(self, text='Click me', command= lambda: stored_functions().add_boxes(self)) button.grid(row=11, column=1) class stored_functions(): make = ['Ford', 'Toyota', 'Honda'] models = [['F-150', 'Mustang', 'Explorer'], ['Camry', 'Corolla', 'Tacoma'], ['Civic', 'CRV', 'Accord']] def add_boxes(self, main_window): for row in range(10): # 直接用局部变量存储当前行控件,不需要存入self make_selection = Combobox(main_window, value=self.make, state='readonly', width=10) make_selection.current(0) make_selection.grid(row=row, column=1) model_selection = Combobox(main_window, value=self.models[0], state='readonly', width=10) model_selection.current(0) model_selection.grid(row=row, column=2) # 用lambda默认参数保存当前行的车型下拉框实例,避免迟绑定问题 make_selection.bind('<<ComboboxSelected>>', lambda event, m=model_selection: self.update_models(event.widget, m)) def update_models(self, make_cb, model_cb): # 直接操作传入的当前行品牌、车型下拉框 make_idx = self.make.index(make_cb.get()) model_cb.config(values=self.models[make_idx]) model_cb.current(0) if __name__ == "__main__": app = SLS_v1() app.mainloop()
内容的提问来源于stack exchange,提问作者Lzypenguin
相关产品推荐
相关产品推荐

