小能豆

TKinter Treeview 中的层次结构

py

我一直试图在 Gtk 中使用数据库中的数据创建分层 TreeView,但一直没有成功(创建具有未知数据集长度的分层 Gtk.TreeStore)。我发现在 TKinter 中我几乎可以做我想做的事情,但是存在一些问题。

  1. 如果一个节点具有与另一个节点相同的值,Python 会抛出以下错误:
    add_node(k, v, x)
  File "/home/bigbird/tvTk3.py", line 10, in add_node
    tree.insert(k, 1, i, text=i,values=[myList2[x][1]])
  File "/usr/lib/python3.10/tkinter/ttk.py", line 1361, in insert
    res = self.tk.call(self._w, "insert", parent, index,
_tkinter.TclError: Item Electric already exists

有可能存在同名的节点吗?我应该做哪些更改来避免这种情况?

  1. 我希望将与每个值关联的数字插入到树视图的第 1 列中。但是行 values=[myList[x][1]] 不会随着每个新节点而改变。如何获取行中的关联数字?

有人能帮我实现这个吗?非常感谢。

import tkinter as tk
from tkinter import ttk as ttk

myList = [['Board', 71], ['Book', 8], ['Breadboard', 6], ['Cables', 48], ['Capacitor', 9], ['Capacitor | Ceramic', 10], ['Capacitor | Electrolytic', 11], ['Circuits', 73], ['Circuits | 555 Timer', 77], ['Circuits | Audio', 76], ['Connector', 12], ['Connectors', 49], ['Drill', 54], ['Drill | Electric', 56], ['Drill | Manual', 55], ['Screwdriver', 32], ['Screwdriver | Electric', 58], ['Screwdriver | Manual', 57], ['Veraboard', 7], ['Wire', 35], ['Wire | Jumper', 36], ['Wire | Solid Core', 37], ['Wire | Stranded', 38]]
# MyList2 replaces ['Screwdriver | Electric', 58], ['Screwdriver | Manual', 57], of MyList with ['Screwdriver | Electrical', 58], ['Screwdriver | Hand', 57],
myList2 = [['Board', 71], ['Book', 8], ['Breadboard', 6], ['Cables', 48], ['Capacitor', 9], ['Capacitor | Ceramic', 10], ['Capacitor | Electrolytic', 11], ['Circuits', 73], ['Circuits | 555 Timer', 77], ['Circuits | Audio', 76], ['Connector', 12], ['Connectors', 49], ['Drill', 54], ['Drill | Electric', 56], ['Drill | Manual', 55], ['Screwdriver', 32], ['Screwdriver | Electrical', 58], ['Screwdriver | Hand', 57], ['Veraboard', 7], ['Wire', 35], ['Wire | Jumper', 36], ['Wire | Solid Core', 37], ['Wire | Stranded', 38]]
# /57036493/
def add_node(k, v,x):
    for i, j in v.items():
        tree.insert(k, 1, i, text=i,values=[myList[x][1]]) # MyList2 will work, MyList does not
        if isinstance(j, dict):
            add_node(i, j,x)

# /59767830/, /52971687/
tree = {}
for path in myList: # MyList2 will work, MyList does not
    node = tree
    for level in path[0].split(' | '):
        if level:
            node = node.setdefault(level, dict())

# /57036493/
hierarchy = tree
root = tk.Tk()
root.geometry("900x900")
tree = ttk.Treeview(root)
ttk.Style().configure('Treeview', rowheight=30)
tree["columns"] = ("one")
tree.column("one")

x=0
for k, v in hierarchy.items():
    tree.insert("", 1, k, text=k, values=[myList[x][1]]) # MyList2 will work, MyList does not
    add_node(k, v, x)
    x+=1

tree.pack(expand=True, fill='both')
root.mainloop()

阅读 14

收藏
2025-01-10

共1个答案

小能豆

有可能有同名的节点吗?

我不确定你说的“名称”是什么意思。文本相同?是的。id 相同?不是。元素标识符必须是唯一的。但是,id 不必与你看到的文本匹配。

我应该改变什么来避免这种情况?

简单的解决方案是让 tkinter 计算每个元素的 id。例如,只需省略第三个位置参数:

tree.insert(k, 1, text=i, values=[myList[x][1]])

如果您需要该 id,该insert方法将返回它。

element_id = tree.insert(k, 1, text=i, values=[myList[x][1]])
2025-01-10