如何在python Tkinter中更新字典的值
我有一个python tkinter应用程序,它有两个下拉列表和两个单选按钮 -几年来第一次下降 -这两个单选按钮是颜色和导航 -第三个下拉菜单是区域选择 现在,对于每个车型年款,都有不同的列和导航字典。根据您选择的是颜色还是导航,区域将发生变化。每个单选按钮在字典中都有自己的键。1表示颜色,2表示导航 我使用如何在python Tkinter中更新字典的值,python,python-2.7,tkinter,Python,Python 2.7,Tkinter,我有一个python tkinter应用程序,它有两个下拉列表和两个单选按钮 -几年来第一次下降 -这两个单选按钮是颜色和导航 -第三个下拉菜单是区域选择 现在,对于每个车型年款,都有不同的列和导航字典。根据您选择的是颜色还是导航,区域将发生变化。每个单选按钮在字典中都有自己的键。1表示颜色,2表示导航 我使用trace查找下拉列表和导航中的更改,如果第一个下拉列表更改,我调用函数callback1;如果单选按钮更改,我调用函数callback2 这是我的代码,我留下了足够的注释,以便让大家理
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中
这个问题有什么解决方案吗?由于区域取决于年份和单选按钮选择,因此您只需要一个回调,它使用这两个信息来填充区域下拉小部件。此回调方法也可以从
\uuuu init\uuuu()
调用,以在第一次选择词典时考虑到实际选择的年份,以防止出现错误,例如在代码中将“2014”放在下拉列表中,但复制2017年的词典
将每年的信息保存在按年份键入的字典中可以简化代码,并使其对数据的更改更加健壮
下面是代码的更新版本(也有更好的名称,并且在应用程序实例上没有不必要的属性):
嗨,非常感谢你的帮助。一个问题:您添加名称的if条件是什么。在哪里可以阅读更多关于它的内容来理解呢?Python文档中有一个非常简短的部分<代码>\uuuu名称\uuuu绑定到模块名称,但模块未导入但作为程序启动时除外。因此,如果您使用惯用的
if
条件导入模块,则不会发生任何事情-main()
不会被调用,因为\uuu name\uuu
等于模块名称。这对于在其他模块中使用部分模块的测试(手动或自动)来说是很好的,一些工具也希望模块可以导入而不会产生副作用。
#!/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()