简体   繁体   English

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

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

I have this sample code I am running.我有这个正在运行的示例代码。 I am creating a window, and when I load the template page and click the "Click me" button, it adds 20 boxes on the screen.我正在创建一个 window,当我加载模板页面并单击“单击我”按钮时,它会在屏幕上添加 20 个框。 10 rows, 2 wide. 10行,2宽。 Column 1 is Car makes, and column 2 is Models.第 1 列是汽车品牌,第 2 列是型号。

When I click the Make box in row 1, and change it from Ford to Toyota, I want the model combobox in row 1 to change to show the Toyota models.当我单击第 1 行中的 Make 框并将其从 Ford 更改为 Toyota 时,我希望第 1 行中的 model combobox 更改为显示丰田车型。 But it only works for the last row.但它只适用于最后一行。 Is it possible to get each row to work?是否可以让每一行工作?

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

You have used same variables for car brands and models selection, so the variables refer the last set after the for loop.您在汽车品牌和车型选择中使用了相同的变量,因此这些变量引用了 for 循环之后的最后一组。

You need to pass the model combobox to update_models() using default value of argument:您需要使用参数的默认值将 model combobox 传递给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)

Note that it is not necessary to use instance variables inside the for loop.请注意,没有必要在 for 循环中使用实例变量。 Also those StringVar s are not used at all, so the functions can be simplified as below:那些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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM