尝试在 python 中用 json/dictionary 递归填充 ttk.treeview

Trying to recursively populate a ttk.treeview with json/dictionary in python

我是 python 的新手,但有 java 经验。非常不同的动物。我有一种方法可以根据遍历目录结构来创建 json/dictionary,我在它创建 json 的地方使用它,如下所示。 我正在尝试获取另一种方法来基于它填充树视图。我在 Whosebug 上看到了几个例子,并试图遵循它们。下面是我想出的,但在浏览第一个目录后它总是出错,就像它忘记了它在哪里。返回以下错误:

Traceback (most recent call last):
  File "temp.py", line 147, in <module>
    load_treeview_from_project_dictionary(myData, tree_view)
  File "temp.py", line 134, in load_treeview_from_project_dictionary
    load_treeview_from_project_dictionary(c, tree_view, int(c['index']))
  File "temp.py", line 136, in load_treeview_from_project_dictionary
    tree_view.insert(parent_id, "end", text=c['name'], values=("", ""))
  File "C:\Users\...\AppData\Local\Programs\Python\Python39\lib\tkinter\ttk.py", line 1364, in insert
    res = self.tk.call(self._w, "insert", parent, index, *opts)
_tkinter.TclError: Item 1 not found

我花了几个小时试图重构并解决这个问题,但没有成功。我现在正在联系这个伟大的社区,指出我的方式的错误! 请帮忙。

import json
import tkinter
from tkinter import ttk
from tkinter.ttk import Label


myData = {
    "name": "MyRoot",
    "type": "directory",
    "index": 0,
    "children": [
        {
            "name": "SubDir1",
            "type": "directory",
            "index": 1,
            "children": [
                {
                    "name": "apic.png",
                    "type": "file"
                }
            ]
        },
        {
            "name": "SubDir2",
            "type": "directory",
            "index": 2,
            "children": [
                {
                    "name": "somefile.txt",
                    "type": "file"
                },
                {
                    "name": "anotherfile.txt",
                    "type": "file"
                }
            ]
        },
        {
            "name": "SubDir3",
            "type": "directory",
            "index": 3,
            "children": []
        },
        {
            "name": "SubDir4",
            "type": "directory",
            "index": 4,
            "children": [
                {
                    "name": "asomefile.txt",
                    "type": "file"
                },
                {
                    "name": "bsomefile.txt",
                    "type": "file"
                },
                {
                    "name": "csomefile.txt",
                    "type": "file"
                },
                {
                    "name": "dsomefile.txt",
                    "type": "file"
                },
                {
                    "name": "esomefile.txt",
                    "type": "file"
                }
            ]
        },
        {
            "name": "SubDir5",
            "type": "directory",
            "index": 5,
            "children": [
                {
                    "name": "NesterDir1",
                    "type": "directory",
                    "index": 6,
                    "children": []
                }
            ]
        },
        {
            "name": "SubDir6",
            "type": "directory",
            "index": 7,
            "children": []
        },
        {
            "name": "SubDir7",
            "type": "directory",
            "index": 8,
            "children": []
        },
        {
            "name": "SubDir8",
            "type": "directory",
            "index": 9,
            "children": []
        },
        {
            "name": "SubDir9",
            "type": "directory",
            "index": 10,
            "children": []
        },
        {
            "name": "SubDir10",
            "type": "directory",
            "index": 11,
            "children": []
        },
        {
            "name": "SubDir11",
            "type": "directory",
            "index": 12,
            "children": []
        }
    ]
}


def load_treeview_from_project_dictionary(data, my_tree_view, parent_id=None):
    print("this:" + data['name'] + " called function!")
    if parent_id is None:
        my_tree_view.insert("", "0", text=data['name'], values=("", ""))  # applies to first iteration only
    if data['children'] is not None:
        for c in data['children']:
            print("child: " + c['name'])
            if c['type'] == "directory":
                my_tree_view.insert('', int(c['index']), text=c['name'], values=("", ""))
                load_treeview_from_project_dictionary(c, my_tree_view, int(c['index']))
            else:
                my_tree_view.insert(parent_id, "end", text=c['name'], values=("", ""))
                load_treeview_from_project_dictionary(c, my_tree_view, parent_id)


root = tkinter.Tk()

main_label = Label(root, text="Directory Tree")
tree_view = ttk.Treeview(root, height=23)

tree_view.heading("#0", text="Directory Structure")

load_treeview_from_project_dictionary(myData, tree_view)

main_label.pack()
tree_view.pack()

root.mainloop()

提前致谢!

所以。在查看了 D.L 发布的教程 link 并梳理了我的代码并一遍又一遍地调试之后,我得出的结论是递归太多了。观察流程我发现该方法总是在第一个文件添加到树中后停止。在文件插入后进行递归调用修复了大部分问题。我仔细检查了插入过程,发现我可以将 json 中的索引用于树视图的 iid。然后我决定在插入条目时使用 treeview.move 将条目放置在我想要的位置会更有效。下面是我想出的,效果很好。 我在这里为遇到相同问题的任何其他人发布这个。在代码之后,有一个结果树视图的屏幕截图(或者 link 由于我rank-我稍后会尝试修复)

import json
import tkinter
from tkinter import ttk
from tkinter.ttk import Label

myData = {
    "name": "MyRoot",
    "type": "directory",
    "index": 0,
    "children": [
        {
            "name": "SubDir1",
            "type": "directory",
            "index": 1,
            "children": [
                {
                    "name": "apic.png",
                    "type": "file"
                }
            ]
        },
        {
            "name": "SubDir2",
            "type": "directory",
            "index": 2,
            "children": [
                {
                    "name": "somefile.txt",
                    "type": "file"
                },
                {
                    "name": "anotherfile.txt",
                    "type": "file"
                }
            ]
        },
        {
            "name": "SubDir3",
            "type": "directory",
            "index": 3,
            "children": []
        },
        {
            "name": "SubDir4",
            "type": "directory",
            "index": 4,
            "children": [
                {
                    "name": "asomefile.txt",
                    "type": "file"
                },
                {
                    "name": "bsomefile.txt",
                    "type": "file"
                },
                {
                    "name": "csomefile.txt",
                    "type": "file"
                },
                {
                    "name": "dsomefile.txt",
                    "type": "file"
                },
                {
                    "name": "esomefile.txt",
                    "type": "file"
                }
            ]
        },
        {
            "name": "SubDir5",
            "type": "directory",
            "index": 5,
            "children": [
                {
                    "name": "NestedDir1",
                    "type": "directory",
                    "index": 6,
                    "children": [
                        {
                            "name": "yetAnotherfile.txt",
                            "type": "file"
                        }
                    ]
                }
            ]
        },
        {
            "name": "SubDir6",
            "type": "directory",
            "index": 7,
            "children": []
        },
        {
            "name": "SubDir7",
            "type": "directory",
            "index": 8,
            "children": []
        },
        {
            "name": "SubDir8",
            "type": "directory",
            "index": 9,
            "children": []
        },
        {
            "name": "SubDir9",
            "type": "directory",
            "index": 10,
            "children": []
        },
        {
            "name": "SubDir10",
            "type": "directory",
            "index": 11,
            "children": []
        },
        {
            "name": "SubDir11",
            "type": "directory",
            "index": 12,
            "children": []
        }
    ]
}


def load_treeview_from_project_dictionary(data, my_tree_view, parent_id=None):
    print('this:' + data['name'] + ' called function!')
    if parent_id is None:
        my_tree_view.insert('', '0', text=data['name'], iid=0)  # applies to first iteration only
    for c in data['children']:
        print('child: ' + c['name'])
        if c['type'] == 'directory':
            my_tree_view.insert('', 'end', text=c['name'], iid=c['index'])
            my_tree_view.move(c['index'], data['index'], 'end')
            load_treeview_from_project_dictionary(c, my_tree_view, data['index'])
        else:
            file_index = my_tree_view.insert('', 'end', text=c['name'])
            my_tree_view.move(file_index, data['index'], 'end')


root = tkinter.Tk()

main_label = Label(root, text='Directory Tree')
tree_view = ttk.Treeview(root, height=23)

tree_view.heading('#0', text='Directory Structure')

load_treeview_from_project_dictionary(myData, tree_view)

main_label.pack()
tree_view.pack()

root.mainloop()

Treeview screenshot