Reputation:
I am trying to create an explorer in tkinter
. I just heard about an hierarchical Treeview
. Therefore, I am trying to implement it.
Here, I tried using recursion, because for a for
loop, one cannot know the number of subdirectories and files inside a particular folder.
Here is my recursive function.
def new_folder(path,arrs):
for arr in arrs:
if os.path.isdir(path+"\\"+arr):
try:
a1=os.listdir(path+"\\"+arr)
new_folder(path+"\\"+arr,a1)
except PermissionError:
pass
else:
print(path+"\\"+arr)
path="C:\\Users\\91996\\Documents"
arrss=os.listdir(path)
new_folder(path,arrss)
Whenever I run this code, it gives me this error:
Traceback (most recent call last):
File "c:/Users/91996/Documents/Visual studio code/focd.py", line 47, in <module>
new_folder(path,arrss,'item'+str(2))
File "c:/Users/91996/Documents/Visual studio code/focd.py", line 37, in new_folder
new_folder(path+"\\"+arr,a1,values[:-1]+str(3))
File "c:/Users/91996/Documents/Visual studio code/focd.py", line 44, in new_folder
treeview.move(values,'item1','end')
File "C:\Program Files\Python3.8.6\lib\tkinter\ttk.py", line 1388, in move
self.tk.call(self._w, "move", item, parent, index)
_tkinter.TclError: Item item3 not found
Here is my code.
from tkinter import *
import os
# Importing ttk from tkinter
from tkinter import ttk
# Creating app window
app = Tk()
# Defining title of the app
app.title("GUI Application of Python")
# Defining label of the app and calling a geometry
# management method i.e, pack in order to organize
# widgets in form of blocks before locating them
# in the parent widget
ttk.Label(app, text ="Treeview(hierarchical)").pack()
# Creating treeview window
treeview = ttk.Treeview(app)
# Calling pack method on the treeview
treeview.pack()
# Inserting items to the treeview
# Inserting parent
treeview.insert('', '0', 'item1',
text ='Documents')
# Inserting child
i=3
def new_folder(path,arrs,values):
global i
for arr in arrs:
if os.path.isdir(path+"\\"+arr):
try:
a1=os.listdir(path+"\\"+arr)
new_folder(path+"\\"+arr,a1,values[:-1]+str(i))
i+=1
except PermissionError:
pass
else:
treeview.insert(values,'end',text=arr)
print(path+"\\"+arr)
treeview.move(values,'item1','end')
path="C:\\Users\\91996\\Documents"
arrss=os.listdir(path)
new_folder(path,arrss,'item'+str(i))
app.mainloop()
Currently, this is the Treeview
which I made using a for
loop. However, I feel this is not good because it will not fetch files and folders. I had to make 8 nested for
loops to get all files and folders up to the 8th sub-folder. But recursion can solve all the problem. The only problem lies in implementing it with ttk.Treeview
.
Upvotes: 0
Views: 1603
Reputation: 605
You start with:
i=3
...
new_folder(path,arrss,'item'+str(i))
If you add these lines to your function, you will see that item3
does not exist yet.
def new_folder(path,arrs,values):
print('item1 ->', treeview.exists('item1'), treeview.item('item1'))
print(values, '->', treeview.exists(values))
global i
for arr in arrs:
print(f"action: treeview.insert(values,'end',text=arr)")
print(f"insert arguments: parent='{values}', index='end', text='{arr}'")
Output:
item1 -> True {'text': 'Documents', 'image': '', 'values': '', 'open': 0, 'tags': ''}
item3 -> False
action: treeview.insert(values,'end',text=arr)
insert arguments: parent='item3', index='end', text='file.ext'
Traceback (most recent call last):
...
res = self.tk.call(self._w, "insert", parent, index, *opts)
_tkinter.TclError: Item item3 not found
You need to get the iid's of all found folders in the loop and use them as the current parents.
from tkinter import *
import os
from tkinter import ttk
app = Tk()
app.title("GUI Application of Python")
ttk.Label(app, text="Treeview(hierarchical)").pack()
treeview = ttk.Treeview(app, show='tree')
treeview.pack(fill='both', expand=True)
def new_folder(parent_path, directory_entries,
parent_iid, f_image, d_image):
"""Creates a graphical representation of the structure
of subdirectories and files in the specified parent_path.
Recursive tree building for large directories can take some time.
:param parent_path: directory path, string
:param directory_entries: List[str]
a list containing the names of the entries in the parent_path
obtained using os.listdir()
:param parent_iid: unique identifier for a treeview item, string
:param f_image: file icon, tkinter.PhotoImage
:param d_image: directory icon, tkinter.PhotoImage
:return: None
"""
for name in directory_entries:
item_path = parent_path+os.sep+name
# optional: file does not exist or broken symbolic link
#if not os.path.exists(item_path):
#print("Skipped:", item_path)
#continue
if os.path.isdir(item_path):
# set subdirectory node
subdir_iid = treeview.insert(parent=parent_iid,
index='end',
text=name,
image=d_image)
try:
# pass the iid of the subdirectory as parent iid
# all files/folders found in this subdirectory
# will be attached to this subdirectory node
subdir_entries = os.listdir(item_path)
new_folder(parent_path=item_path,
directory_entries=subdir_entries,
parent_iid=subdir_iid,
f_image=f_image,
d_image=d_image)
except PermissionError:
pass
else:
treeview.insert(parent=parent_iid,
index='end',
text=name,
image=f_image)
print(item_path)
# png 16x16 -> base64 strings for tkinter.PhotoImage
file_img = """
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABGdB
TUEAALGPC/xhBQAAAAlwSFlzAAAScwAAEnMBjCK5BwAAAalJREFU
OE99kUtLAmEUhg38Af6a6he06SJIF8FFREVtqkVEkBB2IcJIRDAk
80KrNq3CWihuuuh4GVIwM9BSa0bHUXGc8X7p1Bc6jtLLxzAwz3Pm
nPMNcaWySCR6CYVoOgMvzWaz3W63Wq1GowFPsVg8PDIqkUjg019A
gEOSJHAowEHAhDidzmAwGI3FEPZTXSDwafiJ3W5nWRbH8TSVGSAI
aBDi8TiGYT6fz2QyCwU+Dc0ADanX67XfWK3W/4QOjYRqtWqxWIQC
mhKh/NpAVyoVs/GcclwzabI7NF/odILocrnsPFwvGRcS6uUeob8T
RDOxMGuYz2vkfsdtVxhIg1AqMqnTRUYrD+iU2Vy+R+jvBMpTN+aC
Zi6umo2+RXouDmgkFJ4fyLNNNvUFdJFM0kfTuQOpfk9ZZLmuQBBE
Z4Np/VrtapVSKwqf7wmlLLc/iR9vGAyGnrWCgC4ImmZpKqVbKeoV
xK4sq5pI7kgjAfzCZBIK/PWX8jRxspRVjVPbY8FLLcdxfQKZ8vlx
j9eLebxuzOPGMO/j/YdyJro1dWezPblc4defieF8A+ZBma193+p6
AAAAAElFTkSuQmCC
"""
dir_img = """
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABGdB
TUEAALGPC/xhBQAAAAlwSFlzAAAScgAAEnIBXmVb4wAAAihJREFU
OE990vtv0kAcAPDh4wd/8w/yp5n4i4kkmizoBMKcRIfG7YepWSSZ
MSTGSXQao8wtjIw5ZkJEJ4+O0CGvoWhSCmw0sFJaHoU+GEJbyDax
EwMjQS+Xy30v97m7791JOF4Y+FMOBEJsj508PXD8lERyoj3Yp4ig
XclNRSlyg0F0TFxLRbXFyAMqaarkQrXabmfO4eqdoBRWtgQnujGM
+DRVbIYnTU3Wvrf7hcubGRToTOsFvK3V/JZyy6KeCXL7CZc3CEVj
k7bTO85/A+FDgwr6rKNIQEtu6XnC0Ch/+j+wCSXXulke994vxh/X
sNkGaaXTfXfYVLbEIwk2gbQBpstxz0QOmq6mdXxxmUr1A8Wg4i8o
rLoWh2C3hvhxr5KcqhMLVMrRJ4eCX97irL/qFh6fdxkvQoAaj4yz
iTv17KsyYu8D8t7hg+q7fXahjr50GaWQawT7OkbDN3/u6JIflQxb
qXN8zzsQniv7tGGv9Czx/tz64gXIqcTCagoaqWxpcO/dKBzL4oTI
uu+QBYaaBX2DeBgyDoJmKQzIMyEVE5Wz8HXMO7W29tnnD8TiiS5A
HbIGPi1kJn3zZzdWLh2CoIKGZHRUlXJPzs29XVoy40SuC6p0lgyo
+PS4e/aM8835GHALDWvY2LVybAxcVs881XtAUEyjC8SEGPx7bfu2
4/mgzfwiEgSz4dcJixRxjq5YVtEM1r6oHiDGuP9RwHS1TOaP/tCj
/d+VL1STn8NNZQAAAABJRU5ErkJggg==
"""
file_image = PhotoImage(data=file_img)
dir_image = PhotoImage(data=dir_img)
# adds a parent item to the tree
# and returns the item's iid value (generated automatically)
parent_iid = treeview.insert(parent='',
index='0',
text='Documents',
open=True,
image=dir_image)
start_path = os.path.expanduser(r"~\Documents")
start_dir_entries = os.listdir(start_path)
# inserting items to the treeview
new_folder(parent_path=start_path,
directory_entries=start_dir_entries,
parent_iid=parent_iid,
f_image=file_image,
d_image=dir_image)
app.mainloop()
Upvotes: 2