我使用的是TTK树视图控件来实现文件夹/路径选择对话框。 这是预期不同的是我的水平滚动条不会激活所有的工作。 无论多么广泛的文件夹路径变为水平,而且不管如何缩小窗口,永远不会出现水平滑块。 垂直滚动虽然可以正常使用。
我认定它要么某种限制的时候,你只能使用在TreeView一列,或只是一个新手的错误与配置和连接部件。 我敢打赌后者。
与对话实例拉大到显示完整的文件夹深度:
对话缩小到水平滚动应该激活(但没有)点:
这里是我的GUI布局代码:
winDirSel = tk.Toplevel()
winDirSel.title('Select Test Directory...')
tvwDirSel = ttk.Treeview(winDirSel,
height=10,padding=3,
show='tree')
lblTestDir = tk.Label(winDirSel, relief=tk.SUNKEN,
justify=tk.LEFT, anchor=tk.W,
textvariable=ctrlTestDir,width=80)
scbHDirSel = ttk.Scrollbar(winDirSel,
orient=tk.HORIZONTAL,
command=tvwDirSel.xview)
scbVDirSel = ttk.Scrollbar(winDirSel,
orient=tk.VERTICAL,
command=tvwDirSel.yview)
tvwDirSel.configure(xscrollcommand=scbHDirSel.set,
yscrollcommand=scbVDirSel.set)
lblTestDir.grid(row=0,column=0,sticky=tk.EW)
tvwDirSel.grid(row=1,column=0,sticky=tk.NSEW)
scbVDirSel.grid(row=1,column=1,sticky=tk.NS)
scbHDirSel.grid(row=2,column=0,sticky=tk.EW)
winDirSel.rowconfigure(1,weight=1)
winDirSel.columnconfigure(0,weight=1)
OK,有打有后minwidth
和stretch
,我想我有一个更好的处理。 水平滚动由柱边走出去的窗口的边界,该列的不是内容的触发。 所以,你可以用这些参数来强制列更宽,从而迫使滚动。
问题是,虽然你失去再列宽的自动调整,以适应树本身的宽度。 您可能已迫使它很宽,以适应任何(假设)有可能文件夹深度,或者你住在列的右边界的文件夹名取截断。
因此,底线:它只是一个小部件本身的限制。 (至少相对于它我的平台,微软Windows的行为。)
以下是我终于想出了显示TreeView
这是懒加载(由于文件的这个答案 ),这是一个内部PanedWindow
(在wxPython中的术语SplitterWindow)与一起Notebook
。 滚动条是自动显示/隐藏的需要,这要归功于这个例子 。
import os
import Tkinter as tk
import ttk as ttk
from 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
abspath = os.path.abspath(path)
self.nodes = dict()
self.insert_node('', abspath, abspath)
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):
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()
root.geometry("800x600")
app = App(root, path='.')
root.mainloop()
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.font as tk_font
class TreeListBox:
def __init__(self, master, root, dict_group):
self.master = master
self.root = root
self.dict_group = dict_group
self.level = 0
self.setup_widget_tree()
self.build_tree(self.root, '')
def setup_widget_tree(self):
container_tree = tk.Frame(self.master, width=250, height=300)
container_tree.propagate(False)
container_tree.pack(side="left", fill='y')
self.tree = ttk.Treeview(container_tree, show="tree", selectmode='browse')
fr_y = tk.Frame(container_tree)
fr_y.pack(side='right', fill='y')
tk.Label(fr_y, borderwidth=1, relief='raised', font="Arial 8").pack(side='bottom', fill='x')
sb_y = tk.Scrollbar(fr_y, orient="vertical", command=self.tree.yview)
sb_y.pack(expand='yes', fill='y')
fr_x = tk.Frame(container_tree)
fr_x.pack(side='bottom', fill='x')
sb_x = tk.Scrollbar(fr_x, orient="horizontal", command=self.tree.xview)
sb_x.pack(expand='yes', fill='x')
self.tree.configure(yscrollcommand=sb_y.set, xscrollcommand=sb_x.set)
self.tree.pack(fill='both', expand='yes')
def build_tree(self, parent, id_stroki):
self.level += 1
id = self.tree.insert(id_stroki, 'end', text=parent)
# -----------------
col_w = tk_font.Font().measure(parent)
if col_w > 1000:
col_w -= 400
elif col_w > 500:
col_w -= 200
elif col_w > 300:
col_w -= 100
col_w = col_w + 25 * self.level
if col_w > self.tree.column('#0', 'width'):
self.tree.column('#0', width=col_w)
# -----------------
for element in sorted(self.dict_group[parent]):
self.build_tree(element, id)
self.level -= 1
if __name__ == '__main__':
dict_group = {'Nomenclature': ['ABC1', 'ABC2'],
'ABC1': ['ABC3', 'ABC4'],
'ABC2': ['ABC5'],
'ABC3': ['ABC______________________________________6'],
'ABC4': ['ABC--------------------------------------8'],
'ABC5': ['ABC######################################9'],
'ABC______________________________________6': [],
'ABC--------------------------------------8': [],
'ABC######################################9': []
}
root = tk.Tk()
myTest = TreeListBox(root, 'Nomenclature', dict_group)
root.mainloop()