0

I want to use the same tree widget for different reports. To make this work I need to modify the header every time before inserting new data. But I can't get the widget to behave the way I want it to: whenever I change the header/width, an empty column will come out of nowhere. Is there something I can do to prevent that or I must destroy and recreate a new treeview everytime?

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
tree = ttk.Treeview(root, selectmode='browse')
tree.grid(row=0,column=0)
tree_header = ("One", "Two", "Three", "Four", "Five")
tree_width = (100, 100, 100, 100, 100)
tree["columns"] = tree_header
tree['show'] = 'headings'

for i in range(len(tree_header)):
    tree.column(tree_header[i],width=tree_width[i], anchor="w", stretch = False)
    tree.heading(tree_header[i], text=tree_header[i], anchor='w')
tree.insert("",tk.END,text="",value=(1,2,3,4,5))

def click_me():
    tree.delete(*tree.get_children())
    new_header = ("Six","Seven","Eight","Nine","Ten")
    new_width = (120, 80, 120, 80, 100)
    tree["columns"] = new_header
    tree['show'] = 'headings'
    for i in range(len(new_header)):
        tree.column(new_header[i],width=new_width[i],anchor="w", stretch = False)
        tree.heading(new_header[i],text=new_header[i],anchor="w")
    a_button.config(command=click_me_again)
    tree.insert("", tk.END, text="", value=(6, 7, 8, 9, 10))

def click_me_again():
    tree.delete(*tree.get_children())
    tree["columns"] = tree_header
    tree['show'] = 'headings'
    for i in range(len(tree_header)):
        tree.column(tree_header[i],width=tree_width[i],  anchor="w", stretch = False)
        tree.heading(tree_header[i], text=tree_header[i], anchor='w')
    a_button.config(command=click_me)
    tree.insert("", tk.END, text="", value=(1, 2, 3, 4, 5))

a_button = tk.Button(root,text="Click me",command=click_me)
a_button.grid(row=1,column=0)

root.mainloop()

1 Answer 1

1

This example changes yours a little bit. I think it's a benefit for the user if the Treeview expands with its container.

But that change doesn't solve the problem.

I found that shrinking the column widths still leaves the Treeview widget with the original width, hence the white space. Then if I resize the window using the right border, and it passes in the right direction over the last column right border, it will catch the header and the headers and window will resize together again...

What I do below is to set the container (root window) width to the calculated width of all the columns, after a width change. I account also for the column separator pixels (otherwise a window width resize will have to catch again as described above):

You can still detach the last header from the window border manually, opening whitespace, But you can also force a minwidth. And rewriting headers fixes it. I think you can also capture that event and force the window width to follow, if that matters.

I don't know it there is a simpler way to fix this behaviour, and I don't know also if it is expected or more like a bug. If I have a pre-determined number of columns and I am on 'headings' not 'tree headings' why the extra whitespace?

import tkinter as tk
from tkinter import ttk

def change_headers():
    global headers
    headers = (headers[0]+'A', headers[1]+'B', headers[2]+'C')
    widths = (50, 50, 50)
    tree['columns'] = headers
    for i, header in enumerate(headers):
        tree.heading(header, text=header)
        tree.column(header, width=widths[i])
    w = sum(width for width in widths) + len(widths)-1
    h = root.winfo_reqheight()
    root.wm_geometry('{}x{}'.format(w,h))
    root.update()

root = tk.Tk()
tree = ttk.Treeview(root)
button = ttk.Button(root, text='Change Headers', command=change_headers)

tree.grid(row=0, column=0, sticky=tk.NSEW)
button.grid(row=1, column=0, sticky=tk.EW)

root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)

headers = ('A', 'B', 'C')
widths = (150, 150, 150)
tree['show'] = 'headings'
tree['columns'] = headers
for i, header in enumerate(headers):
    tree.heading(header, text=header)
    tree.column(header, width=widths[i])

root.mainloop()
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, but i had to maintain the same size for my GUI due to other layouts. I am still trying to figure out if there's a proper way to fix it though
If the size is fixed and the columns shrink, obviously there has to be some remaining whitespace. What is really strange is that the new Tree width becomes larger than the original total width, wthout need, in the first headers change.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.