对于ttk Treeview小部件,不会激活水平滚动

时间:2013-01-16 13:47:42

标签: python-2.7 treeview tkinter scrollbar ttk

我正在使用ttk Treeview小部件来实现文件夹/路径选择对话框。除了我的水平滚动条不会激活外,它都按预期工作。无论文件夹路径横向有多宽,无论窗口有多窄,都不会出现水平滑块。垂直滚动工作正常。

当你在树视图中只使用一列时,或者只是在配置和连接小部件时出现新手错误时,我认为它要么是某种限制。我打赌后者。

扩展对话框以显示完整文件夹深度的示例:

full width

对话框缩小到水平滚动应该激活的程度(但不是):

narrowed width

这是我的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)

3 个答案:

答案 0 :(得分:10)

好的,在玩了minwidthstretch之后,我想我有更好的处理方法。水平滚动是由列边缘从窗口边界出来而不是列的内容触发的。因此,您可以使用这些参数来强制列更宽,从而强制滚动。

但问题是你失去了自动调整列宽以适应树本身的宽度。您要么必须强制它以适应任何(假定的)可能的文件夹深度,要么您在文件夹名称被截断在列的右边界处。

所以底线:它只是小部件本身的限制。 (至少关于它在我的平台上的行为,MS Windows。)

答案 1 :(得分:3)

这是我最终想出来的TreeView文件,这些文件是PanedWindow内部的Notebook懒惰加载的文件(感谢this answer)(SplitterWindow in wxPython术语)和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() 。由于this example,滚动条会根据需要自动显示/隐藏。

{{1}}

答案 2 :(得分:1)

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()