4

Using this Python script, which is my first attempt to learn how ttk.Treeview works (the extra copy of autoscroll is just to split the horizontal and vertical callbacks):

import Tkinter as tk
import ttk

class Test():
def __init__(self, parent=None):
    self.win = tk.Toplevel()
    self.win.grid_columnconfigure(0, weight=1)
    self.win.grid_rowconfigure(0, weight=1)     

    self.treeFrame = ttk.LabelFrame(self.win, text='Test Scrolling tk.Treeview')
    self.treeFrame.grid(row=0, column=0, padx=5, pady=5, sticky='nsew')
    self.treeFrame.grid_columnconfigure(0, weight=1)
    self.treeFrame.rowconfigure(0, weight=1)

    def autoscrollv(sbar, first, last):
        print 'vert first:%s, last:%s' % (first,last)
        first, last = float(first), float(last)
        if first <= 0 and last >= 1:
            sbar.grid_remove()
        else:
            sbar.grid()
        sbar.set(first, last)

    def autoscrollh(sbar, first, last):
        print 'horz first:%s, last:%s' % (first,last)           
        first, last = float(first), float(last)
        if first <= 0 and last >= 1:
            sbar.grid_remove()
        else:
            sbar.grid()
        sbar.set(first, last)

    vsb = ttk.Scrollbar(self.treeFrame, orient="vertical")
    hsb = ttk.Scrollbar(self.treeFrame, orient="horizontal")

    self.tree = ttk.Treeview(self.treeFrame, height=10, 
                             yscrollcommand=lambda f, l: autoscrollv(vsb, f, l), 
                             xscrollcommand=lambda f, l: autoscrollh(hsb, f, l))  
    self.tree.column("#0", minwidth=400, stretch=True)

    vsb['command'] = self.tree.yview
    hsb['command'] = self.tree.xview

    self.tree.grid(row=0, column=0, sticky='nsew')
    vsb.grid(column=1, row=0, sticky='ns')
    hsb.grid(column=0, row=1, sticky='ew')

    self.tree.insert('', 'end', 'xyz', text='abc'*20)
    for i in range(30):
        self.tree.insert('xyz', 'end', text='%s' % i + 'xyz'*40)

    self.win.mainloop()

if __name__ == "__main__":
    test = Test()

I see the following behavior: When I first run the program, the output looks like this: initial state.

If I expand the window until the horizontal scrollbar shuts off, it looks like this:last just goes to 1.0

If I continue to expand the window, here is all the text shown: closed item width

My first question is, how can I get xscrollcommand to recognize the actual width of the text, rather than using the value for minwidth?

Going back to the state in the second image, if I open the item, it goes to this:vscroll on

My second question is nearly the same as the first. How do I get it to recognize the new width of the item after it is opened?

If I change minwidth=400 to width=400, the horizontal scrollbar never appears.

Summary: while the vertical scrollbar works as I would expect and reacts to the actual lines of text being displayed (rather than the ttk.Treeview setting for height), the horizontal scrollbar only seems to care about the value for minwidth. I thought of using something like below, especially if there is an equivalent for ttk themed widgets. But, the setting for minwidth doesn't take effect after populating the tree, although I can change the value for width at that point. Is there a way to force a change to minwidth?

minwidth=tkFont.Font().measure(text)
self.tree.column('#0', minwidth=tcw)

Sorry for the extra window; that part of Tkinter confuses me no end...

taras
  • 6,566
  • 10
  • 39
  • 50
LMO
  • 515
  • 7
  • 18
  • It's well-known that Tk's Treeview widget has issues w/ horizontal scrolling. I just drafted a lengthy question on a particular scenario you might want to look at, on the chance it gives you any ideas: https://stackoverflow.com/q/49715456/ – Kumba Apr 08 '18 at 07:30

0 Answers0