0

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

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

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()
4

1 回答 1

2

您在汽车品牌和车型选择中使用了相同的变量,因此这些变量引用了 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 循环中使用实例变量。而且那些StringVars 根本没有使用,所以功能可以简化如下:

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)
于 2021-11-23T05:03:39.530 回答