基于此答案(第一个答案的第二部分-“更新:作为@ArtOfWarfare ...”)-Tkinter: Treeview widget,我试图用所有驱动器填充Treeview,但仅填充正常工作的最后一个驱动器。有任何想法吗?我知道有一种方法可以从一开始就填充驱动器,但对于所有驱动器,我认为太多了。
import os, string
import tkinter as tk
from tkinter import ttk
from tkinter.scrolledtext import ScrolledText
class App(object):
def __init__(self, master, path):
splitter = tk.PanedWindow(master, orient=tk.HORIZONTAL)
# left-side
frame_left = tk.Frame(splitter)
self.tree = ttk.Treeview(frame_left, show='tree')
ysb = ttk.Scrollbar(frame_left, orient='vertical', command=self.tree.yview)
xsb = ttk.Scrollbar(frame_left, orient='horizontal', command=self.tree.xview)
# right-side
frame_right = tk.Frame(splitter)
nb = ttk.Notebook(frame_right)
page1 = ttk.Frame(nb)
page2 = ttk.Frame(nb)
text = ScrolledText(page2)
# overall layout
splitter.add(frame_left)
splitter.add(frame_right)
splitter.pack(fill=tk.BOTH, expand=1)
# left-side widget layout
self.tree.grid(row=0, column=0, sticky='NSEW')
ysb.grid(row=0, column=1, sticky='ns')
xsb.grid(row=1, column=0, sticky='ew')
# left-side frame's grid config
frame_left.columnconfigure(0, weight=1)
frame_left.rowconfigure(0, weight=1)
# right-side widget layout
text.pack(expand=1, fill="both")
nb.add(page1, text='One')
nb.add(page2, text='Two')
nb.pack(expand=1, fill="both")
# setup
self.tree.configure(yscrollcommand=lambda f, l:self.autoscroll(ysb,f,l),
xscrollcommand=lambda f, l:self.autoscroll(xsb,f,l))
# use this line instead of the previous, if you want the scroll bars to
#always be present, but grey-out when uneeded instead of disappearing
#self.tree.configure(yscrollcommand=ysb.set, xscrollcommand=xsb.set)
self.tree.heading('#0', text='Project tree', anchor='w')
self.tree.column("#0",minwidth=1080, stretch=True)
# add default tree node
# we create a list of dictionaries. We access them with self.nodes[i][i] -> {}
self.nodes = [{i: {}} for i in range(len(all_drives))]
i = 0
for path in all_drives:
os.chdir(os.path.join(path,'\\')) #to get '<letter>:\' all over
abspath = os.path.abspath(path)
self.insert_node('', abspath, abspath,i)
i += 1
self.tree.bind('<<TreeviewOpen>>', self.open_node)
def autoscroll(self, sbar, first, last):
#Hide and show scrollbar as needed.
first, last = float(first), float(last)
if first <= 0 and last >= 1:
sbar.grid_remove()
else:
sbar.grid()
sbar.set(first, last)
def insert_node(self, parent, text, abspath,i):
node = self.tree.insert(parent, 'end', text=text, open=False)
if os.path.isdir(abspath):
self.nodes[i][i][node] = abspath
self.tree.insert(node, 'end')
def open_node(self, event):
node = self.tree.focus() #below another method for child/parent id
# Finding the parent id
item_iid = self.tree.selection()[0] # child id
parent_iid = self.tree.parent(item_iid) # parent id
if parent_iid:
print(self.tree.item(parent_iid)['text'])
else:
print(self.tree.item(item_iid)['text'])
# We check if node/id is find in the list of keys
keys_list = []
for j in range(len(self.nodes)):
keys_list.extend(iter(self.nodes[j][j].keys()))
print(keys_list)
for j in range(len(self.nodes)):
if keys_list[j] == node:
print(j)
k = j
abspath = self.nodes[k][k].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),k)
if __name__ == '__main__':
root = tk.Tk()
root.geometry("800x600")
# get the drives - without removable
all_drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)]
app = App(root, path=all_drives)
root.mainloop()
#
更新:我已解决了该问题,您的代码如下。
import os, string
import tkinter as tk
from tkinter import ttk
from tkinter.scrolledtext import ScrolledText
class App(object):
def __init__(self, master, path):
splitter = tk.PanedWindow(master, orient=tk.HORIZONTAL)
# left-side
frame_left = tk.Frame(splitter)
self.tree = ttk.Treeview(frame_left, show='tree')
ysb = ttk.Scrollbar(frame_left, orient='vertical', command=self.tree.yview)
xsb = ttk.Scrollbar(frame_left, orient='horizontal', command=self.tree.xview)
# right-side
frame_right = tk.Frame(splitter)
nb = ttk.Notebook(frame_right)
page1 = ttk.Frame(nb)
page2 = ttk.Frame(nb)
text = ScrolledText(page2)
# overall layout
splitter.add(frame_left)
splitter.add(frame_right)
splitter.pack(fill=tk.BOTH, expand=1)
# left-side widget layout
self.tree.grid(row=0, column=0, sticky='NSEW')
ysb.grid(row=0, column=1, sticky='ns')
xsb.grid(row=1, column=0, sticky='ew')
# left-side frame's grid config
frame_left.columnconfigure(0, weight=1)
frame_left.rowconfigure(0, weight=1)
# right-side widget layout
text.pack(expand=1, fill="both")
nb.add(page1, text='One')
nb.add(page2, text='Two')
nb.pack(expand=1, fill="both")
# setup
self.tree.configure(yscrollcommand=lambda f, l:self.autoscroll(ysb,f,l),
xscrollcommand=lambda f, l:self.autoscroll(xsb,f,l))
# use this line instead of the previous, if you want the scroll bars to
#always be present, but grey-out when uneeded instead of disappearing
#self.tree.configure(yscrollcommand=ysb.set, xscrollcommand=xsb.set)
self.tree.heading('#0', text='Project tree', anchor='w')
self.tree.column("#0",minwidth=1080, stretch=True)
# ===== add default nodes to tree =====
# we create a list of dictionaries. To access use: self.nodes[i][i] -> {}
self.nodes = [{i: {}} for i in range(len(all_drives))]
# create a list for nodes -> func. insert_node()
self.node_ins = ['' for i in range(len(all_drives))]
# create a list for nodes -> func. open_node()
self.node_open = ['' for i in range(len(all_drives))]
# add/insert all drives
i = 0
for path in all_drives:
os.chdir(os.path.join(path,'\\')) #to get '<letter>:\' all over
abspath = os.path.abspath(path)
self.insert_node('', abspath, abspath,i)
i += 1
self.tree.bind('<<TreeviewOpen>>', self.open_node)
def autoscroll(self, sbar, first, last):
#Hide and show scrollbar as needed.
first, last = float(first), float(last)
if first <= 0 and last >= 1:
sbar.grid_remove()
else:
sbar.grid()
sbar.set(first, last)
def insert_node(self, parent, text, abspath,i):
self.node_ins[i] = self.tree.insert(parent, 'end', text=text, open=False)
if os.path.isdir(abspath):
self.nodes[i][i][self.node_ins[i]] = abspath
self.tree.insert(self.node_ins[i], 'end')
def open_node(self, event):
node = self.tree.focus() #below, another method for item id
#item_id = self.tree.selection()[0] # selected item id
k = 0
# We check if the node/id is find in the list of dictionaries
for j in range(len(self.nodes)):
if node in iter(self.nodes[j][j].keys()):
k = list(self.nodes[j].keys())[0]
self.node_open[k] = node
abspath = self.nodes[k][k].pop(self.node_open[k], None)
try:
if abspath:
self.tree.delete(self.tree.get_children(self.node_open[k]))
for p in os.listdir(abspath):
self.insert_node(self.node_open[k], p, os.path.join(abspath, p),k)
except OSError as e: # we can put the error into a status bar
#print("Error:",str(e))# usually is a PermissionError
pass
if __name__ == '__main__':
root = tk.Tk()
root.geometry("800x600")
# get the drives - without removable
all_drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)]
app = App(root, path=all_drives)
root.mainloop()