Python tkinter - 如何使用字典制作两个链接的组合框
Python tkinter - How to make two linked combo boxes using a dictionary
目的:两个链接的组合框,一个显示字典键。另一个显示所选键的值。
我已经用字典键的值填充了第一个组合框,并将其转换为列表,以便在组合框中很好地显示。
已设置默认值,用于收集第二个组合框所需的数据。这里一切正常,我卡住的地方是如何更新
当第一个组合框当前值更改时第二个组合框的值。
到目前为止的代码
from tkinter import Tk, StringVar, ttk
dict_values = {
"Beer": ["Ale", "Lager", "Stout"],
"Spirits": ["Brandy", "Gin", "Rum"],
"Wine": ["White","Red","Rose"]
}
#convert keys to list for displaying in the first combobox
box1= []
for key in dict_values:
box1.append(key)
from tkinter import Tk, StringVar, ttk
class Application:
def __init__(self, parent):
self.parent = parent
self.combo()
def combo(self):
#First Combobox
self.box_value = StringVar()
self.box = ttk.Combobox(self.parent, textvariable=self.box_value,
state='readonly')
self.box['values'] = box1
self.box.current(0)
self.box.grid(column=0, row=0)
#Second Combobox
self.box_value2 = StringVar()
self.box2 = ttk.Combobox(self.parent, textvariable=self.box_value2,
state='readonly')
self.box2['values'] = dict_values[self.box.get()]
self.box2.grid(column=1, row=0)
if __name__ == '__main__':
root = Tk()
root.minsize(800, 600)
app = Application(root)
root.mainloop()
代码缺少将 <<ComboboxSelected>>
事件绑定到将在 self.box
中进行选择时执行的回调
所以添加
self.box.bind("<<ComboboxSelected>>",self.selected)
注意 self.selected
是你必须实现的新方法,这里是一个例子
def selected(self,e):
#print('selected value ->',self.box.get(),self.box_value.get())
self.box2.configure(values = dict_values[self.box_value.get()] )
self.box2.current(0)
完整代码
#<<ComboboxSelected>>
from tkinter import Tk, StringVar, ttk
dict_values = {
"Beer": ["Ale", "Lager", "Stout"],
"Spirits": ["Brandy", "Gin", "Rum"],
"Wine": ["White","Red","Rose"]
}
#convert keys to list for displaying in the first combobox
box1= []
for key in dict_values:
box1.append(key)
from tkinter import Tk, StringVar, ttk
class Application:
def __init__(self, parent):
self.parent = parent
self.combo()
# Modification 2
def selected(self,e):
#print('selected value ->',self.box.get(),self.box_value.get())
self.box2.configure(values = dict_values[self.box_value.get()] )
self.box2.current(0)
def combo(self):
#First Combobox
self.box_value = StringVar()
self.box = ttk.Combobox(self.parent, textvariable=self.box_value,
state='readonly')
# Modification 1
self.box.bind("<<ComboboxSelected>>",self.selected)
self.box['values'] = box1
self.box.current(0)
self.box.grid(column=0, row=0)
#Second Combobox
self.box_value2 = StringVar()
self.box2 = ttk.Combobox(self.parent, textvariable=self.box_value2,
state='readonly')
self.box2['values'] = dict_values[self.box.get()]
self.box2.grid(column=1, row=0)
if __name__ == '__main__':
root = Tk()
root.minsize(800, 600)
app = Application(root)
root.mainloop()
您可以使用 validate
和 validatecommand
来完成此操作。无需向组合框添加 bind
。如果 validate
设置为 "all"
或 "focus"
。
,则每次单击组合框时 validatecommand
都会 运行
A StringVar
是不必要的开销,您的文档结构有点奇怪。下面的示例解决了这些问题并为您的问题提供了解决方案。
from tkinter import Tk
from tkinter.ttk import Combobox
class Application(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
self.options = {
"Beer": ["Ale", "Lager", "Stout"],
"Spirits": ["Brandy", "Gin", "Rum"],
"Wine": ["White","Red","Rose"]
}
#delegate between init and config so the Combobox kwargs are not a mile long
self.cb1 = Combobox(self, state="readonly", values=[*self.options])
self.cb1.config(validate="focus", validatecommand=self.populate_slave)
self.cb1.current(0)
self.cb1.grid(column=0, row=0)
self.cb2 = Combobox(self, state="readonly")
self.cb2.grid(column=1, row=0)
#manually run the validatecommand function once to init cb2 items
#this way it will always be correct regardless of the item you start cb1 with
self.populate_slave()
def populate_slave(self):
self.cb2['values'] = self.options[self.cb1.get()]
self.cb2.current(0)
return True #must return True or validatecommand will quit
if __name__ == "__main__":
app = Application()
app.minsize(800, 600)
app.title('My Application')
app.mainloop()
目的:两个链接的组合框,一个显示字典键。另一个显示所选键的值。
我已经用字典键的值填充了第一个组合框,并将其转换为列表,以便在组合框中很好地显示。 已设置默认值,用于收集第二个组合框所需的数据。这里一切正常,我卡住的地方是如何更新 当第一个组合框当前值更改时第二个组合框的值。
到目前为止的代码
from tkinter import Tk, StringVar, ttk
dict_values = {
"Beer": ["Ale", "Lager", "Stout"],
"Spirits": ["Brandy", "Gin", "Rum"],
"Wine": ["White","Red","Rose"]
}
#convert keys to list for displaying in the first combobox
box1= []
for key in dict_values:
box1.append(key)
from tkinter import Tk, StringVar, ttk
class Application:
def __init__(self, parent):
self.parent = parent
self.combo()
def combo(self):
#First Combobox
self.box_value = StringVar()
self.box = ttk.Combobox(self.parent, textvariable=self.box_value,
state='readonly')
self.box['values'] = box1
self.box.current(0)
self.box.grid(column=0, row=0)
#Second Combobox
self.box_value2 = StringVar()
self.box2 = ttk.Combobox(self.parent, textvariable=self.box_value2,
state='readonly')
self.box2['values'] = dict_values[self.box.get()]
self.box2.grid(column=1, row=0)
if __name__ == '__main__':
root = Tk()
root.minsize(800, 600)
app = Application(root)
root.mainloop()
代码缺少将 <<ComboboxSelected>>
事件绑定到将在 self.box
所以添加
self.box.bind("<<ComboboxSelected>>",self.selected)
注意 self.selected
是你必须实现的新方法,这里是一个例子
def selected(self,e):
#print('selected value ->',self.box.get(),self.box_value.get())
self.box2.configure(values = dict_values[self.box_value.get()] )
self.box2.current(0)
完整代码
#<<ComboboxSelected>>
from tkinter import Tk, StringVar, ttk
dict_values = {
"Beer": ["Ale", "Lager", "Stout"],
"Spirits": ["Brandy", "Gin", "Rum"],
"Wine": ["White","Red","Rose"]
}
#convert keys to list for displaying in the first combobox
box1= []
for key in dict_values:
box1.append(key)
from tkinter import Tk, StringVar, ttk
class Application:
def __init__(self, parent):
self.parent = parent
self.combo()
# Modification 2
def selected(self,e):
#print('selected value ->',self.box.get(),self.box_value.get())
self.box2.configure(values = dict_values[self.box_value.get()] )
self.box2.current(0)
def combo(self):
#First Combobox
self.box_value = StringVar()
self.box = ttk.Combobox(self.parent, textvariable=self.box_value,
state='readonly')
# Modification 1
self.box.bind("<<ComboboxSelected>>",self.selected)
self.box['values'] = box1
self.box.current(0)
self.box.grid(column=0, row=0)
#Second Combobox
self.box_value2 = StringVar()
self.box2 = ttk.Combobox(self.parent, textvariable=self.box_value2,
state='readonly')
self.box2['values'] = dict_values[self.box.get()]
self.box2.grid(column=1, row=0)
if __name__ == '__main__':
root = Tk()
root.minsize(800, 600)
app = Application(root)
root.mainloop()
您可以使用 validate
和 validatecommand
来完成此操作。无需向组合框添加 bind
。如果 validate
设置为 "all"
或 "focus"
。
validatecommand
都会 运行
A StringVar
是不必要的开销,您的文档结构有点奇怪。下面的示例解决了这些问题并为您的问题提供了解决方案。
from tkinter import Tk
from tkinter.ttk import Combobox
class Application(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
self.options = {
"Beer": ["Ale", "Lager", "Stout"],
"Spirits": ["Brandy", "Gin", "Rum"],
"Wine": ["White","Red","Rose"]
}
#delegate between init and config so the Combobox kwargs are not a mile long
self.cb1 = Combobox(self, state="readonly", values=[*self.options])
self.cb1.config(validate="focus", validatecommand=self.populate_slave)
self.cb1.current(0)
self.cb1.grid(column=0, row=0)
self.cb2 = Combobox(self, state="readonly")
self.cb2.grid(column=1, row=0)
#manually run the validatecommand function once to init cb2 items
#this way it will always be correct regardless of the item you start cb1 with
self.populate_slave()
def populate_slave(self):
self.cb2['values'] = self.options[self.cb1.get()]
self.cb2.current(0)
return True #must return True or validatecommand will quit
if __name__ == "__main__":
app = Application()
app.minsize(800, 600)
app.title('My Application')
app.mainloop()