在 tkinter 的分层树视图中递归排列所有文件夹和文件
Recursively arrange all folders and files in a hierarchical treeview in tkinter
我正在尝试在 tkinter
中创建一个资源管理器。我刚刚听说了分层 Treeview
。因此,我正在尝试实现它。
在这里,我尝试使用递归,因为对于 for
循环,无法知道特定文件夹中的子目录和文件的数量。
这是我的递归函数。
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)
每当我 运行 这段代码时,它都会给我这个错误:
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
这是我的代码。
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()
目前,这是我使用 for
循环制作的 Treeview
。但是,我觉得这不好,因为它不会获取文件和文件夹。我必须进行 8 次嵌套 for
循环才能将所有文件和文件夹获取到第 8 个子文件夹。但是递归可以解决所有问题。唯一的问题在于用 ttk.Treeview
.
来实现它
您开始于:
i=3
...
new_folder(path,arrss,'item'+str(i))
如果将这些行添加到函数中,您将看到 item3
尚不存在。
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}'")
输出:
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
您需要获取循环中所有找到的文件夹的 iid,并将它们用作当前父文件夹。
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()
我正在尝试在 tkinter
中创建一个资源管理器。我刚刚听说了分层 Treeview
。因此,我正在尝试实现它。
在这里,我尝试使用递归,因为对于 for
循环,无法知道特定文件夹中的子目录和文件的数量。
这是我的递归函数。
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)
每当我 运行 这段代码时,它都会给我这个错误:
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
这是我的代码。
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()
目前,这是我使用 for
循环制作的 Treeview
。但是,我觉得这不好,因为它不会获取文件和文件夹。我必须进行 8 次嵌套 for
循环才能将所有文件和文件夹获取到第 8 个子文件夹。但是递归可以解决所有问题。唯一的问题在于用 ttk.Treeview
.
您开始于:
i=3
...
new_folder(path,arrss,'item'+str(i))
如果将这些行添加到函数中,您将看到 item3
尚不存在。
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}'")
输出:
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
您需要获取循环中所有找到的文件夹的 iid,并将它们用作当前父文件夹。
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()