Display directory content with tkinter Treeview widget
29,008
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 <<TreeviewOpen>>
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('<<TreeviewOpen>>', 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()
Author by
user2213550
Updated on July 24, 2022Comments
-
user2213550 almost 2 years
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 the sub-files inside the project file, Any Ideas?
Thanks in advance!
-
Donal Fellows almost 11 yearsAssuming that the questioner was really doing mapping of the filesystem, that's a good solution.
-
ArtOfWarfare over 9 years@DonalFellows - This is a good answer no matter what the questioner was really trying to do, because it really answers what they asks. It's exactly what I wanted (an example of Treeview - I'm just getting started with tk/ttk and need to see some more examples before I'm ready to write stuff from scratch on my own.)
-
ArtOfWarfare over 7 yearsOver two years later, I have a different thought on this - won't it be really inefficient? You're going to populate directories the user may never end up expanding. Surely there's a way to defer calling
process_directory
until the user actually opens it? -
A. Rodas over 7 years@ArtOfWarfare Sure it's possible, see my updated answer. If the directory tree is large, the lazy load may be a better solution - however, the example gets a little more complex IMO.
-
Chris Collett over 2 yearsNot an answer, just a lengthy comment to the actual answer above. Recommending modifications should be done in comments.
-
Al Mahdi almost 2 yearsGreat. But its not horizontally scrollable. Sub directories are overflowed from the treeview.