我有一个 python tkinter 应用程序,带有两个下拉菜单和两个单选按钮
-第一个下拉列表是年份
-两个单选按钮是颜色和导航
-第三个下拉菜单是区域选择
现在,每个型号年份都有不同的列和导航词典。根据您选择颜色还是导航,区域面积将会改变。每个单选按钮在字典中都有自己的键。 1 用于颜色,2 用于导航
我正在使用trace
来查找下拉列表和导航中的更改,如果第一个下拉列表发生变化,我将调用函数callback1,如果单选按钮发生变化,我将调用callback2
这是我的代码,我留下了足够的注释以便于理解程序:
from Tkinter import *
class App:
def __init__(self, master):
self.radioButtonVariable = IntVar()
self.text = StringVar()
frame = Frame(master, width=500, height=500)
frame.pack_propagate(0) # set the flag to use the size
frame.pack()
#dictionaries for evey year [NOTE: 1 is for Color and 2 is for Navigation]
self.dict17 = {1: ['China', 'Europe', 'North America'],
2: ['Australia', 'China', 'Europe']}
self.dict16 = {1: ['China ', 'Europe ', 'North America '],
2: ['Australia ', 'China ', 'Germany']}
self.dict15 = {1: ['China ', 'Europe-Russia ', 'North America '],
2: ['Australia ', 'New Zealand', 'England', 'Israel Region', 'Latin America Region', 'Middle East Region', 'North America Region', 'Philipines _Region', 'South American _Region', 'Turkey _Region']}
self.dict14 = {1: ['China', 'Europe-Russia ', 'South America '],
2: ['Philipines Region', 'Turkey _Region']}
self.dict = self.dict17.copy() #set default dictionary to 2017
#label for first dropdown
self.MY_LABEL = Label(frame, text="Model Year:", anchor=W)
self.MY_LABEL.grid(row=0, column=1)
self.variable = StringVar(master)
self.variable.set("2014") #set default value to 2014 of dropdown
#create the dropdown of model year
self.w = OptionMenu(frame, self.variable, "2014", "2015", "2016", "2017")
self.w.grid(row=0, column=2)
self.variable.trace("w", self.callback1) #check for changes in the variable and call callback function
#radio buttons
self.COL = Radiobutton(frame, text="Color", variable=self.radioButtonVariable, value=1)
self.COL.grid(row=1, column=2)
self.NAV = Radiobutton(frame, text="Navigation", variable=self.radioButtonVariable, value=2)
self.NAV.grid(row=1, column=3)
#region label
self.REGION_LABEL = Label(frame, text="Region:", anchor=W)
self.REGION_LABEL.grid(row=2,column=1)
#check for changes in the radio buttons and call callback function 2
self.radioButtonVariable.trace("w", self.callback2)
self.variable2 = StringVar(master)
#create second dropdown
self.w2 = OptionMenu(frame, self.variable2, "")
self.w2.grid(row=2, column=2)
#this function clears the deault dictionary and copies a new one to it (SOMETHING IS WRONG HERE)
def callback1(self, *args):
module = self.variable.get()
if module == "2017":
self.dict.clear()
self.dict = self.dict17.copy()
elif module == "2016":
self.dict.clear()
self.dict = self.dict16.copy()
elif module == "2015":
self.dict.clear()
self.dict == self.dict15.copy()
else:
self.dict.clear()
self.dict == self.dict14.copy()
#this function calls the second callback function and changes the dropdown the the new dictionary that is set
def callback2(self, *args):
countries = self.dict[self.radioButtonVariable.get()]
self.variable2.set(countries[0])
menu = self.w2["menu"]
menu.delete(0, 'end')
for country in countries:
menu.add_command(label=country, command=lambda nation=country: self.variable2.set(nation))
root = Tk()
root.wm_title("application")
app = App(root)
root.mainloop()
错误:
现在,如果下拉列表中的第一个选择是默认选项(2017),则该程序绝对可以正常工作。因此,如果您在颜色和导航之间切换,区域中下拉列表的实际值将会改变
但是,一旦您选择了其他年份,例如 2015 年,区域将不会更改,并且我会收到此错误:
line 81, in callback2
countries = self.dict[self.radioButtonVariable.get()]
KeyError: 1
我相信这是因为我正在清除字典并复制新字典,但是似乎新字典没有被复制,所以它没有找到正确的键。所以问题出在函数回调2中
这个问题有解决办法吗?
最佳答案
由于区域取决于年份和单选按钮选择,因此您只需要一个回调即可使用这两种信息来填充区域下拉小部件。也可以从 __init__()
调用此回调方法,以在第一次选择字典时考虑到选择的实际年份,以防止出现错误,例如在代码中将“2014”放入下拉列表中但复制2017年词典。
将每年的信息保存在按年份作为键的字典中可以简化代码,并使其在应对数据更改时更加稳健。
这是代码的更新版本(也具有更好的名称,并且应用程序实例上没有不必要的属性):
#!/usr/bin/env python
from __future__ import absolute_import, division, print_function
import Tkinter as tk
from functools import partial
COLOR, NAVIGATION = 1, 2
class Application(object):
def __init__(self, master):
frame = tk.Frame(master)
frame.pack()
self.year2data = {
2017: {
COLOR: ['China', 'Europe', 'North America'],
NAVIGATION: ['Australia', 'China', 'Europe'],
},
2016: {
COLOR: ['China ', 'Europe ', 'North America '],
NAVIGATION: ['Australia ', 'China ', 'Germany'],
},
2015: {
COLOR: ['China ', 'Europe-Russia ', 'North America '],
NAVIGATION: [
'Australia ', 'New Zealand', 'England', 'Israel Region',
'Latin America Region', 'Middle East Region',
'North America Region', 'Philipines _Region',
'South American _Region', 'Turkey _Region'
],
},
2014: {
COLOR: ['China', 'Europe-Russia ', 'South America '],
NAVIGATION: ['Philipines Region', 'Turkey _Region'],
},
}
self.current_data = None
tk.Label(frame, text='Model Year:', anchor=tk.E).grid(row=0, column=1)
years = sorted(self.year2data.iterkeys())
self.model_year_var = tk.IntVar(master)
self.model_year_var.set(years[0])
tk.OptionMenu(frame, self.model_year_var, *years).grid(
row=0, column=2, columnspan=2
)
self.model_year_var.trace('w', self.update_region)
self.color_or_navigation_var = tk.IntVar()
tk.Radiobutton(
frame, text='Color', variable=self.color_or_navigation_var, value=1
).grid(row=1, column=2)
tk.Radiobutton(
frame,
text='Navigation',
variable=self.color_or_navigation_var,
value=2,
).grid(row=1, column=3)
self.color_or_navigation_var.trace('w', self.update_region)
tk.Label(frame, text='Region:', anchor=tk.E).grid(row=2, column=1)
self.region_var = tk.StringVar(master)
self.region_dropdown = tk.OptionMenu(frame, self.region_var, '')
self.region_dropdown.grid(row=2, column=2, columnspan=2)
self.update_region()
def update_region(self, *_args):
self.current_data = self.year2data[self.model_year_var.get()]
color_or_navigation = self.color_or_navigation_var.get()
if color_or_navigation != 0:
regions = self.current_data[color_or_navigation]
menu = self.region_dropdown['menu']
menu.delete(0, tk.END)
for region in regions:
menu.add_command(
label=region, command=partial(self.region_var.set, region)
)
if self.region_var.get() not in regions:
self.region_var.set(regions[0])
def main():
root = tk.Tk()
root.title('application')
_ = Application(root)
root.mainloop()
if __name__ == '__main__':
main()
关于python - 如何在 python Tkinter 中更新字典的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32234266/