Display directory content with tkinter Treeview widget

后端 未结 2 1106
春和景丽
春和景丽 2020-12-05 19:58

At the moment I am working on a program that has its own project files and inside that are like sub-files and I want to know how to use the treeview widget to display all th

2条回答
  •  忘掉有多难
    2020-12-05 20:53

    There is an example in the source code of CPython of how to fill a Treeview recursively with the content of a directory, this is basically how it works (I have removed the event bindings and wrapped it in a class for better readability):

    import os
    import tkinter as tk
    import tkinter.ttk as ttk
    
    class App(tk.Frame):
        def __init__(self, master, path):
            tk.Frame.__init__(self, master)
            self.tree = ttk.Treeview(self)
            ysb = ttk.Scrollbar(self, orient='vertical', command=self.tree.yview)
            xsb = ttk.Scrollbar(self, orient='horizontal', command=self.tree.xview)
            self.tree.configure(yscroll=ysb.set, xscroll=xsb.set)
            self.tree.heading('#0', text=path, anchor='w')
    
            abspath = os.path.abspath(path)
            root_node = self.tree.insert('', 'end', text=abspath, open=True)
            self.process_directory(root_node, abspath)
    
            self.tree.grid(row=0, column=0)
            ysb.grid(row=0, column=1, sticky='ns')
            xsb.grid(row=1, column=0, sticky='ew')
            self.grid()
    
        def process_directory(self, parent, path):
            for p in os.listdir(path):
                abspath = os.path.join(path, p)
                isdir = os.path.isdir(abspath)
                oid = self.tree.insert(parent, 'end', text=p, open=False)
                if isdir:
                    self.process_directory(oid, abspath)
    
    root = tk.Tk()
    path_to_my_project = # ...
    app = App(root, path=path_to_my_project)
    app.mainloop()
    

    Update: As @ArtOfWarfare mentions, it is possible to lazy populate the tree using the <> event. To simulate the closed nodes, I've used an empty child item that is removed when a directory is opened:

    import os
    import tkinter as tk
    import tkinter.ttk as ttk
    
    
    class App(object):
        def __init__(self, master, path):
            self.nodes = dict()
            frame = tk.Frame(master)
            self.tree = ttk.Treeview(frame)
            ysb = ttk.Scrollbar(frame, orient='vertical', command=self.tree.yview)
            xsb = ttk.Scrollbar(frame, orient='horizontal', command=self.tree.xview)
            self.tree.configure(yscroll=ysb.set, xscroll=xsb.set)
            self.tree.heading('#0', text='Project tree', anchor='w')
    
            self.tree.grid()
            ysb.grid(row=0, column=1, sticky='ns')
            xsb.grid(row=1, column=0, sticky='ew')
            frame.grid()
    
            abspath = os.path.abspath(path)
            self.insert_node('', abspath, abspath)
            self.tree.bind('<>', self.open_node)
    
        def insert_node(self, parent, text, abspath):
            node = self.tree.insert(parent, 'end', text=text, open=False)
            if os.path.isdir(abspath):
                self.nodes[node] = abspath
                self.tree.insert(node, 'end')
    
        def open_node(self, event):
            node = self.tree.focus()
            abspath = self.nodes.pop(node, None)
            if abspath:
                self.tree.delete(self.tree.get_children(node))
                for p in os.listdir(abspath):
                    self.insert_node(node, p, os.path.join(abspath, p))
    
    
    if __name__ == '__main__':
        root = tk.Tk()
        app = App(root, path='.')
        root.mainloop()
    

提交回复
热议问题