pythontkintertreetreeviewttkwidgets

create a tree with the ttk.Treeview widget, based on a list


["c:","c:/folder","c:/folder2","c:/folder/file.txt","c:/folder/folder3","c:/folder/folder3/file2.txt","c:/folder2/file3.txt"]

I want with this example that my tree seems like this:

    c:
    |folder
    ||file.txt
    ||folder3
    |||file2.txt
    |folder2
    ||file3.txt

I have tried for loops but it doesnt work.


import tkinter as tk
from tkinter import ttk


def finder(sys):
    def tree_with_sys(parent: tk.Tk, system: list):
        tree = ttk.Treeview(parent)

        #Place where I don't know what to do

        return tree
    win_finder = tk.Tk()
    win_finder.geometry("1800x1000+0+0")
    win_finder.title("Finder")
    tree = tree_with_sys(win_finder, sys)
    tree.pack()
    win_finder.mainloop()

I think that recursives functions may help... maybe ? Thanks for help


Solution

  • I have solved your problem. I have never used tkinter myself but your problem seems simple enough so I decided to give it a try and solve it.

    It is simple. First of all, you don't need to create win_finder, tree is its own window, you are creating two windows here. And the window is too big for what you used as examples. I removed that part without affecting the functionality.

    Now your code gives me a great starting point, tree = ttk.Treeview(tk.Tk()); tree.pack(); tree.main_loop() are what is needed to get the code running.

    Now how to add the nodes? I just created a new file in Visual Studio Code, and inspected the attributes of tree, we need to use insert method of Treeview class instances here.

    insert takes many arguments, the ones that are relevant here are positional arguments parent and index, and optional argument text. text is what is displayed, '' as parent creates are top level node, else the new node is inserted to the specified parent, and index is where the node should be inserted to, 'end' means the node is appended to the end.

    To get what you want, we first need to split the file names by '/' to get the leaves, and we can then loop through each first n levels to check if the corresponding node has been created, we keep track of the nodes in a dict and create the new node if needed by retrieving the identifier of the parent node and add new node using the insert method.

    import tkinter as tk
    from tkinter import ttk
    
    tree = ttk.Treeview(tk.Tk())
    
    names = [
        "c:",
        "c:/folder",
        "c:/folder2",
        "c:/folder/file.txt",
        "c:/folder/folder3",
        "c:/folder/folder3/file2.txt",
        "c:/folder2/file3.txt",
    ]
    
    nodes = {}
    
    for name in names:
        leaves = name.split("/")
        parent = leaves[0]
        if (parent,) not in nodes:
            nodes[(parent,)] = tree.insert("", "end", text=parent)
    
        for i in range(1, len(leaves)):
            if tuple(leaves[: i + 1]) not in nodes:
                nodes[tuple(leaves[: i + 1])] = tree.insert(
                    nodes.get(tuple(leaves[:i])), "end", text=leaves[i]
                )
    
    tree.pack()
    tree.mainloop()
    

    enter image description here