python - 如何在 python Tkinter 中更新字典的值

标签 python python-2.7 tkinter

我有一个 python tkinter 应用程序,带有两个下拉菜单和两个单选按钮

enter image description here

-第一个下拉列表是年份

-两个单选按钮是颜色和导航

-第三个下拉菜单是区域选择

现在,每个型号年份都有不同的列和导航词典。根据您选择颜色还是导航,区域面积将会改变。每个单选按钮在字典中都有自己的键。 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/

相关文章:

python - tensorflow 检查图像在阅读器中

Python:urllib.error.HTTPError:HTTP 错误 525:Origin SSL 握手错误

python - 弃用警告 : invalid escape sequence - what to use instead of\d?

python - 如何使用 Tkinter 在 python 中创建令人印象深刻的 GUI?

Python - While 循环更改变量

python-2.7 - 如何更改 Flask Admin 上的按钮逻辑?

python - 在将字典保存到 CSV 之前忽略一些键值对

Python - isinstance 返回 false

grid - Tkinter 网格列跨度被忽略

python - 如何完全删除 tkinter 中标签的垂直填充?