如何更改在 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)
我有这个示例代码我是运行。我正在创建一个 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)