如何更改在 for 循环中生成的 ttk Combobox 值

How do I change a ttk Combobox values that was made in a for loop

我有这个示例代码我是运行。我正在创建一个 window,当我加载模板页面并单击“单击我”按钮时,它会在屏幕上添加 20 个框。 10 行,2 宽。第 1 列是汽车品牌,第 2 列是型号。

当我单击第 1 行中的“制造”框并将其从 Ford 更改为 Toyota 时,我希望第 1 行中的模型组合框更改为显示 Toyota 模型。但它只适用于最后一行。是否可以让每一行工作?

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_var = tk.StringVar(main_window)
            self.make_options = self.make
            self.make_var.set(self.make_options[0])
            self.make_selection = tk.ttk.Combobox(main_window, value=self.make_options,
                                                     state='readonly', width=10)
            self.make_selection.current(0)
            self.make_selection.bind('<<ComboboxSelected>>', lambda event:
                                                    stored_functions.update_models(self, selection=self.make_selection))
            self.make_selection.grid(row=row, column=1)

            self.model_var = tk.StringVar(main_window)
            self.model_options = self.models[0]
            self.model_var.set(self.model_options[0])
            self.model_selection = tk.ttk.Combobox(main_window, value=self.model_options,
                                                     state='readonly', width=10)
            self.model_selection.current(0)
            self.model_selection.grid(row=row, column=2)

    def update_models(self, selection):
        if selection.get() == 'Ford':
            self.model_options = self.models[0]
        if selection.get() == 'Toyota':
            self.model_options = self.models[1]
        if selection.get() == 'Honda':
            self.model_options = self.models[2]
        self.model_selection.config(values=self.model_options)
        self.model_selection.current(0)

if __name__ == "__main__":
    app = SLS_v1()
    app.mainloop()

您在汽车品牌和车型选择中使用了相同的变量,因此变量参考for循环后的最后一组。

您需要使用参数的默认值将模型组合框传递给 update_models()

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_var = tk.StringVar(main_window)
            self.make_options = self.make
            self.make_var.set(self.make_options[0])
            self.make_selection = tk.ttk.Combobox(main_window, value=self.make_options,
                                                     state='readonly', width=10)
            self.make_selection.current(0)
            self.make_selection.grid(row=row, column=1)

            self.model_var = tk.StringVar(main_window)
            self.model_options = self.models[0]
            self.model_var.set(self.model_options[0])
            self.model_selection = tk.ttk.Combobox(main_window, value=self.model_options,
                                                     state='readonly', width=10)
            self.model_selection.current(0)
            self.model_selection.grid(row=row, column=2)

            # pass the corresponding model combobox to bind function
            self.make_selection.bind(
                '<<ComboboxSelected>>',
                lambda event, peer=self.model_selection: self.update_models(event.widget.get(), peer)
            )

    def update_models(self, selection, model_selection):
        model_options = self.models[self.make.index(selection)]
        model_selection.config(values=model_options)
        model_selection.current(0)

请注意,在 for 循环中没有必要使用实例变量。还有那些 StringVar 根本没有用到,所以函数可以简化如下:

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):
            make_selection = tk.ttk.Combobox(main_window, value=self.make,
                                             state='readonly', width=10)
            make_selection.current(0)
            make_selection.grid(row=row, column=1)

            model_selection = tk.ttk.Combobox(main_window, value=self.models[0],
                                              state='readonly', width=10)
            model_selection.current(0)
            model_selection.grid(row=row, column=2)

            make_selection.bind(
                '<<ComboboxSelected>>',
                lambda event, peer=model_selection: self.update_models(event.widget.get(), peer)
            )

    def update_models(self, selection, model_selection):
        model_options = self.models[self.make.index(selection)]
        model_selection.config(values=model_options)
        model_selection.current(0)