水平滚动不会激活TTK树形控件(Horizontal scrolling won't act

2019-07-18 07:20发布

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

Answer 1:

OK,有打有后minwidthstretch ,我想我有一个更好的处理。 水平滚动由柱边走出去的窗口的边界,该列的不是内容的触发。 所以,你可以用这些参数来强制列更宽,从而迫使滚动。

问题是,虽然你失去再列宽的自动调整,以适应树本身的宽度。 您可能已迫使它很宽,以适应任何(假设)有可能文件夹深度,或者你住在列的右边界的文件夹名取截断。

因此,底线:它只是一个小部件本身的限制。 (至少相对于它我的平台,微软Windows的行为。)



Answer 2:

以下是我终于想出了显示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()


Answer 3:

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


文章来源: Horizontal scrolling won't activate for ttk Treeview widget