【问题标题】:How do I change a ttk Combobox values that was made in a for loop如何更改在 for 循环中创建的 ttk 组合框值
【发布时间】:2022-01-01 15:04:54
【问题描述】:

我正在运行这个示例代码。我正在创建一个窗口,当我加载模板页面并单击“单击我”按钮时,它会在屏幕上添加 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()

【问题讨论】:

    标签: python python-3.x tkinter ttk ttkwidgets


    【解决方案1】:

    您在汽车品牌和车型选择中使用了相同的变量,因此这些变量引用了 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)
    

    【讨论】:

    • 谢谢。这完全符合我的期望。因此,用外行的话来说,当我将 model_selection 组合框作为绑定的参数传递时,它会对那个特定的组合框产生影响,而不是最后一个组合框?非常感谢!
    猜你喜欢
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多