Python:使用UI树显示按键的Dicts,并使用其他任何控件的值显示Dicts

发布于 2021-01-29 15:03:57

我有三个字典,一个提供所有可用选项的列表,另外两个提供选择的子集(一个用于默认设置,一个用于用户选择)。我使用python内置的JSON解析器获得了三个字典。

我想在UI中在左边显示一棵基于字典中键的树,在右边我想显示一个组合框,一个按钮,一个列表框或一些其他适当的小部件来处理数据那把钥匙。我需要这棵树,因为我实际上是在做一份字典,并且我想允许折叠。

到目前为止,我已经研究了tkinter,tkinter的ttk和tix库,它们似乎允许树,但不允许在右边显示可配置列表。我还看到了一些从python的IDLE借来树的示例。

  1. 有没有提供这种功能的GUI工具箱,还是没有这种东西,我必须设计自己的工具?
  2. 如果我必须设计自己的工具,那么有没有您会推荐过tk的GUI工具箱?
  3. 如果不提供这种工具,是否有针对推荐工具箱的GUI设计基础教程?

如果GUI工具包是跨平台兼容的(*
nix和win),并且在可能的情况下可以免费分发,我会更喜欢它。出于兴趣,这里没有关于使用tk创建自定义窗口小部件的教程,我尝试过查找,但是我一直直接针对tk的窗口小部件使用,而不是窗口小部件设计:s

作为一个最小的示例,我暂时放弃了额外的命令,并具有以下内容:

import json
import tkinter as tk
from tkinter import ttk
from pprint import pprint as pprint

def JSONTree(Tree, Parent, Dictionery, TagList = []):
 for key in Dictionery : 
  if isinstance(Dictionery[key],dict): 
   Tree.insert(Parent, 'end', key, text = key)
   TagList.append(key)
   JSONTree(Tree, key, Dictionery[key], TagList)
   pprint(TagList)
  elif isinstance(Dictionery[key],list): 
   Tree.insert(Parent, 'end', key, text = key) # Still working on this
  else : 
   Tree.insert(Parent, 'end', key, text = key, value = Dictionery[key])

if __name__ == "__main__" :
 # Setup the root UI
 root = tk.Tk()
 root.title("JSON editor")
 root.columnconfigure(0, weight=1)
 root.rowconfigure(0, weight=1)
 # Setup Data
 Data = {"firstName": "John",
         "lastName": "Smith",
         "gender": "man",
         "age": 32,
         "address": {"streetAddress": "21 2nd Street",
                     "city": "New York",
                     "state": "NY",
                     "postalCode": "10021"},
         "phoneNumbers": [{ "type": "home", "number": "212 555-1234" },
                          { "type": "fax", "number": "646 555-4567" }]}
 # Setup the Frames
 TreeFrame = ttk.Frame(root, padding = "3")
 TreeFrame.grid(row = 0, column = 0, sticky = tk.NSEW)
 # Setup the Tree
 tree = ttk.Treeview(TreeFrame, columns = ('Values'))
 tree.column('Values', width = 100, anchor = 'center')
 tree.heading('Values', text = 'Values')
 JSONTree(tree, '', Data)
 tree.pack(fill=tk.BOTH, expand = 1)
 # Limit windows minimum dimensions
 root.update_idletasks()
 root.minsize(root.winfo_reqwidth(),root.winfo_reqheight())
 root.mainloop()
关注者
0
被浏览
130
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    好吧,所以它不是很漂亮,将这样的代码投入生产也不会感到很好,但是它确实可以工作。为了使其更加理智和提高生产质量,我可能将JSONTree设置为一个类,并将所有这些代码包装到方法中。这样可以简化和清除代码,并减少将对象传递给事件处理程序的过程。

    import json
    import tkinter as tk
    from tkinter import ttk
    from pprint import pprint as pprint
    
    # opt_name: (from_, to, increment)
    IntOptions = {
        'age': (1.0, 200.0, 1.0),
    }
    
    def close_ed(parent, edwin):
        parent.focus_set()
        edwin.destroy()
    
    def set_cell(edwin, w, tvar):
        value = tvar.get()
        w.item(w.focus(), values=(value,))
        close_ed(w, edwin)
    
    def edit_cell(e):
        w = e.widget
        if w and len(w.item(w.focus(), 'values')) > 0:
            edwin = tk.Toplevel(e.widget)
            edwin.protocol("WM_DELETE_WINDOW", lambda: close_ed(w, edwin))
            edwin.grab_set()
            edwin.overrideredirect(1)
            opt_name = w.focus()
            (x, y, width, height) = w.bbox(opt_name, 'Values')
            edwin.geometry('%dx%d+%d+%d' % (width, height, w.winfo_rootx() + x, w.winfo_rooty() + y))
            value = w.item(opt_name, 'values')[0]
            tvar = tk.StringVar()
            tvar.set(str(value))
            ed = None
            if opt_name in IntOptions:
                constraints = IntOptions[opt_name]
                ed = tk.Spinbox(edwin, from_=constraints[0], to=constraints[1],
                    increment=constraints[2], textvariable=tvar)
            else:
                ed = tk.Entry(edwin, textvariable=tvar)
            if ed:
                ed.config(background='LightYellow')
                #ed.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.W, tk.E))
                ed.pack()
                ed.focus_set()
            edwin.bind('<Return>', lambda e: set_cell(edwin, w, tvar))
            edwin.bind('<Escape>', lambda e: close_ed(w, edwin))
    
    def JSONTree(Tree, Parent, Dictionery, TagList=[]):
        for key in Dictionery :
            if isinstance(Dictionery[key], dict):
                Tree.insert(Parent, 'end', key, text=key)
                TagList.append(key)
                JSONTree(Tree, key, Dictionery[key], TagList)
                pprint(TagList)
            elif isinstance(Dictionery[key], list):
                Tree.insert(Parent, 'end', key, text=key) # Still working on this
            else:
                Tree.insert(Parent, 'end', key, text=key, value=Dictionery[key])
    
    if __name__ == "__main__" :
        # Setup the root UI
        root = tk.Tk()
        root.title("JSON editor")
        root.columnconfigure(0, weight=1)
        root.rowconfigure(0, weight=1)
        # Setup Data
        Data = {
            "firstName": "John",
            "lastName": "Smith",
            "gender": "man",
            "age": 32,
            "address": {
                "streetAddress": "21 2nd Street",
                "city": "New York",
                "state": "NY",
                "postalCode": "10021"},
            "phoneNumbers": [
                { "type": "home", "number": "212 555-1234" },
                { "type": "fax", "number": "646 555-4567" },
            ]}
        # Setup the Frames
        TreeFrame = ttk.Frame(root, padding="3")
        TreeFrame.grid(row=0, column=0, sticky=tk.NSEW)
        # Setup the Tree
        tree = ttk.Treeview(TreeFrame, columns=('Values'))
        tree.column('Values', width=100, anchor='center')
        tree.heading('Values', text='Values')
        tree.bind('<Double-1>', edit_cell)
        tree.bind('<Return>', edit_cell)
        JSONTree(tree, '', Data)
        tree.pack(fill=tk.BOTH, expand=1)
        # Limit windows minimum dimensions
        root.update_idletasks()
        root.minsize(root.winfo_reqwidth(), root.winfo_reqheight())
        root.mainloop()
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看