简体   繁体   English

Python3 - Tkinter - 使用字典创建小部件

[英]Python3 - Tkinter - Widget creation with a dict

Im trying to create widgets dynamically onto the root window of tkinter with a json file as a widget config.我试图在 tkinter 的根tkinter上动态创建小部件,并使用json文件作为小部件配置。 I simplified the code so you can also test things out.我简化了代码,因此您也可以进行测试。 (Im using grid() in my main code but its not necessary here) (我在我的主要代码中使用了grid()但这里没有必要)

The json file contains an items list with each widget in a seperate dict, it can look for example like this. json 文件包含一个items列表,每个小部件都在一个单独的字典中,它可以看起来像这样的例子。

new_dict = {
    "items": [
        {
            "type": "frame",
            "id": "f1"
        },
        {
            "type": "button",
            "id": "b1",
            "text": "Button1"
        }
    ]
}

My goal here to create a widget, stored in the value of the id field, so i can later on change widgets states or other things via .config()我的目标是创建一个小部件,存储在id字段的value中,这样我以后可以通过.config()更改小部件状态或其他内容

( Example: f1 = Frame(root) ) (示例: f1 = Frame(root)

For this example my code looks like this:对于此示例,我的代码如下所示:

( Note: im using locals() to create the specific variables, if there is a better way, please let me know ) 注意:我使用locals()来创建特定变量,如果有更好的方法,请告诉我)

# Example: Change Frame Color to Blue
def change_background(frame_id):
    locals()[frame_id].config(bg=blue)

# Root Window
root = Tk()
root.geometry("800x600")

# Widget Creation
for item in new_dict["items"]:
    if item["type"] == "frame":
        frame_id = item["id"]
        locals()[item["id"]] = Frame(root, width=200, height=200, bg="green")
        locals()[item["id"]].pack(side=BOTTOM, fill=BOTH)
    elif item["type"] == "button":
        locals()[item["id"]] = Button(root, text=item["text"], command=lambda: change_background(frame_id))
        locals()[item["id"]].place(x=50, y=50, anchor=CENTER)

root.mainloop()

Now my problem here is that i cant give the frame id into the change_background function. If i do that im getting following Error:现在我的问题是我无法将frame id提供给change_background function。如果我这样做,我会收到以下错误:

KeyError: 'f1'

I dont quite understand the problem here, because pack() , place() and grid() works fine with each widget.我不太明白这里的问题,因为pack()place()grid()对每个小部件都能正常工作。

As what the name locals means, it stores only local variables.正如名字locals的意思,它只存储局部变量。 So locals() inside the function just contains local variables defined inside the function.所以 function 中的locals()只包含在 function 中定义的局部变量。

It is not recommended to use locals() like this.不建议像这样使用locals() Just use a normal dictionary instead:只需使用普通字典即可:

...
# Example: Change Frame Color to Blue
def change_background(frame_id):
    widgets[frame_id].config(bg="blue")

# Root Window
root = Tk()
root.geometry("800x600")

# Widget Creation
# use a normal dictionary instead of locals()
widgets = {}
for item in new_dict["items"]:
    if item["type"] == "frame":
        frame_id = item["id"]
        widgets[item["id"]] = Frame(root, width=200, height=200, bg="green")
        widgets[item["id"]].pack(side=BOTTOM, fill=BOTH)
    elif item["type"] == "button":
        widgets[item["id"]] = Button(root, text=item["text"], command=lambda: change_background(frame_id))
        widgets[item["id"]].place(x=50, y=50, anchor=CENTER)
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM