我想遞回地將由 DOM 節點組成的嵌套字典資料添加到 Tkinter 的 Treeview 專案中。我期待有一個樹結構,如:
html -> Head
Meta
Title
Body
. . .
不幸的是,我注意到相當重復的欄位。 
這是以下代碼。
import tkinter as tk
from tkinter import ttk
tree_data = {
"tag": "html",
"children": [
{
"tag": "head",
"children": [
{
"tag": "meta",
"children": []
},
{
"tag": "title",
"children": []
}
]
},
{
"tag": "body",
"children": [
{
"tag": "ul",
"children": [
{
"tag": "div",
"children": []
},
{
"tag": "div",
"children": []
},
{
"tag": "div",
"children": []
}
]
},
{
"tag": "div",
"children": [
{
"tag": "ul",
"children": [
{
"tag": "li",
"children": []
},
{
"tag": "li",
"children": []
},
{
"tag": "li",
"children": []
}
]
},
{
"tag": "div",
"children": [
{
"tag": "h1",
"children": []
}
]
},
{
"tag": "div",
"children": [
{
"tag": "h2",
"children": []
}
]
}
]
},
{
"tag": "div",
"children": [
{
"tag": "div",
"children": [
{
"tag": "h1",
"children": []
},
{
"tag": "h1",
"children": []
},
{
"tag": "h2",
"children": []
}
]
}
]
},
{
"tag": "div",
"children": []
}
]
}
]
}
def parent_child(d, ind):
ind = 1
print("this:", ind , d['tag'], "children:", [c['tag'] for c in d['children']])
t = d['tag']
head_tag = tv.insert("", ind, text=f"{t}-{ind}", values=("",""))
for c in d['children']:
ind =1
tv.insert(head_tag, "end", text=c['tag'], values=("",""))
parent_child(c, ind)
root = tk.Tk()
label = tk.Label(root, text="Dom Management")
label.pack()
tv = ttk.Treeview(root, columns=['attribs', 'text'], selectmode='none')
tv.heading('#0', text='Tag')
# tv.heading('attribs', text='Attributes', anchor='center')
tv.heading('text', text='Text', anchor='e')
parent_child(dt, 0)
tv.pack(side=tk.TOP,fill=tk.X)
root.mainloop()
我希望有一個帶有相應添加子項的單個 HTML 根,不幸的是,這是下面的結果。
如何重新調整我的代碼以獲得完美的樹?
uj5u.com熱心網友回復:
首先,我認為您忘記在這行代碼中使用“tree_data”作為函式呼叫的引數。
parent_child(tree_data, 0)
代替
parent_child(dt, 0)
我還修改了JSON資料,讓“標簽”鍵的每個相似值都有一個識別符號,只是為了幫助我們更容易區分,如下:
tree_data = {
"tag": "html",
"children": [
{
"tag": "head",
"children": [
{
"tag": "meta",
"children": []
},
{
"tag": "title",
"children": []
}
]
},
{
"tag": "body",
"children": [
{
"tag": "ul0",
"children": [
{
"tag": "div0",
"children": []
},
{
"tag": "div1",
"children": []
},
{
"tag": "div2",
"children": []
}
]
},
{
"tag": "div3",
"children": [
{
"tag": "ul1",
"children": [
{
"tag": "li0",
"children": []
},
{
"tag": "li1",
"children": []
},
{
"tag": "li2",
"children": []
}
]
},
{
"tag": "div4",
"children": [
{
"tag": "h1-0",
"children": []
}
]
},
{
"tag": "div-5",
"children": [
{
"tag": "h2-0",
"children": []
}
]
}
]
},
{
"tag": "div6",
"children": [
{
"tag": "div7",
"children": [
{
"tag": "h1-1",
"children": []
},
{
"tag": "h1-2",
"children": []
},
{
"tag": "h2-3",
"children": []
}
]
}
]
},
{
"tag": "div-8",
"children": []
}
]
}
]
}
參考您的問題,據我所知,您希望在 TreeView 中顯示 JSON 資料,如下所示:

參考TkInter 的TreeView 物件及其“插入”方法的檔案。
路徑名插入父索引?-id id?選項...
Creates a new item. parent is the item ID of the parent item, or the empty string {} to create a new top-level item. index is an integer, or the value end, specifying where in the list of parent's children to insert the new item. If index is less than or equal to zero, the new node is inserted at the beginning; if index is greater than or equal to the current number of children, it is inserted at the end. If -id is specified, it is used as the item identifier; id must not already exist in the tree. Otherwise, a new unique identifier is generated.
Referring to your "parent_child" function, I noticed some things, that is:
On this line of code,
head_tag = tv.insert("", ind, text=f"{t}-{ind}", values=("",""))
First, you only refer to the automatically-generated identifier once.
Second, referring to the documentation, the second parameter of the insert function is to specify where in the list of parent's children to insert the new item at. Thus, for your case I think you would want to use the "end" string for the second parameter, since you want to always add a new row object at a level on the last position.
Third, still referring to the documentation, if "id" parameter is not specified upon calling the insert function, a new identifier for the newly inserted row in the TreeView object will be returned.
However, in the loop below, you never refer your newly-created row object to anything. Thus, when the recursion happens it will not remember the object that was created before.
for c in d['children']:
ind =1
tv.insert(head_tag, "end", text=c['tag'], values=("",""))
parent_child(c, ind)
您需要修改遞回的邏輯,因為我們希望遞回將父級的行物件識別符號記住給它的子級。請參閱我制作的以下解決方案。
def parent_child(d, parent_id=None):
print("this:", parent_id, d['tag'], "children:", [c['tag'] for c in d['children']])
if parent_id is None:
# This line is only for the first call of the function
parent_id = tv.insert("", "end", text=d['tag'], values=("",""))
for c in d['children']:
# Here we create a new row object in the TreeView and pass its return value for recursion
# The return value will be used as the argument for the first parameter of this same line of code after recursion
parent_child(c, tv.insert(parent_id, "end", text=c['tag'], values=("","")))
# We no longer need to pass the ind parameter
parent_child(tree_data)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/396165.html
上一篇:多個DTO手動初始化
