Search code examples
pythonpython-3.xtkintertreeviewttk

How to add columns to a TTK Treeview using a loop?


I am trying to use the TTK Treeview object to display varying data that require different columns/column names, for some reason when looping through the list of column headings I have created I can never get more than the first and last heading regardless of the numbers although 2 will work.

I have tried adding a sleep section encase it was to create the column to quickly before the heading, I have tried removing the list completely and just trying to create 4 headings in a loop and still the same result.

The treeview object stores the columns in a tuples tree2["columns"] which I print out at the end to verify all the headings references are stored, see example code below.

import tkinter as tk
from tkinter import ttk

headings = ["Heading0", "Heading1", "Heading2", "Heading3"]

root = tk.Tk()
root.title("Add headings")

frame1 = tk.Frame(root)
frame1.pack()

tree = ttk.Treeview(frame1)
tree["columns"] = ("C1", "C2")
tree.column("#0", width=500, minwidth=400, stretch=tk.NO)
tree.column("C1", width=200, minwidth=200, stretch=tk.NO)
tree.column("C2", width=200, minwidth=200, stretch=tk.NO)
tree.heading("#0", text="Name", anchor=tk.W)
tree.heading("C1", text="Type", anchor=tk.W)
tree.heading("C2", text="Index", anchor=tk.W)
print(tree["columns"])

t = {}

for i in range(5):
    t[i] = tree.insert("", i, text="Example " + str(i), values=("val1", "val2"))
tree.pack(expand=True, fill="both")

def create():
    for i, val in enumerate(headings):
        if i == 0:
            tree2.column("#0", width=200, minwidth=200, stretch=tk.NO)
            tree2.heading("#0", text=val, anchor=tk.W)
        elif i == 1:
            tree2["columns"] = tree2["columns"] + ("C1")
            tree2.column("C1", width=800, minwidth=200, stretch=tk.NO)
            tree2.heading("C1", text=val[1], anchor=tk.W)
        else:
            tree2["columns"] = tree2["columns"] + ("C" + str(i),)
            tree2.column("C" + str(i), width=800, minwidth=200, stretch=tk.NO)
            tree2.heading("C" + str(i), text=val, anchor=tk.W)
        print(val)
    print(tree2["columns"])


btn1 = tk.Button(frame1, text="Add", command=create)
btn1.pack(side="top")

tree2 = ttk.Treeview(frame1)


tree2.pack(expand=True, fill="both")

root.mainloop()

here's an example:

Example

The question here adding multiple columns to a treeview demonstrates an issue with getting the correct number of columns but does not give the explicit answer below of calling columns prior to the headings to ensure they are displayed.


Solution

  • Here's the example I mentioned in the comments. This could be formatted better but I'm simply adding onto your code to show how it works. Additionally, there was a bug where you were continuously building onto your tuple with each function call.

    import tkinter as tk
    from tkinter import ttk
    
    headings = ["Heading0", "Heading1", "Heading2", "Heading3"]
    
    root = tk.Tk()
    root.title("Add headings")
    
    frame1 = tk.Frame(root)
    frame1.pack()
    
    tree = ttk.Treeview(frame1)
    tree["columns"] = ("C1", "C2")
    tree.column("#0", width=500, minwidth=400, stretch=tk.NO)
    tree.column("C1", width=200, minwidth=200, stretch=tk.NO)
    tree.column("C2", width=200, minwidth=200, stretch=tk.NO)
    tree.heading("#0", text="Name", anchor=tk.W)
    tree.heading("C1", text="Type", anchor=tk.W)
    tree.heading("C2", text="Index", anchor=tk.W)
    
    t = {}
    
    for i in range(5):
        t[i] = tree.insert("", i, text="Example " + str(i), values=("val1", "val2"))
    tree.pack(expand=True, fill="both")
    
    def create():
        for i, val in enumerate(headings):
            if i == 0:
                tree2.column("#0", width=200, minwidth=200, stretch=tk.NO)
            elif i == 1:
                tree2["columns"] = ("C1", )
                tree2.column("C1", width=800, minwidth=200, stretch=tk.NO)
            else:
                tree2["columns"] = tree2["columns"] + ("C" + str(i), )
                tree2.column("C" + str(i), width=800, minwidth=200, stretch=tk.NO)
    
        for i, val in enumerate(headings):
            if i == 0:
                tree2.heading("#0", text=val, anchor=tk.W)
            elif i == 1:
                tree2.heading("C1", text=val, anchor=tk.W)
            else:
                tree2.heading("C" + str(i), text=val, anchor=tk.W)
    
    
    btn1 = tk.Button(frame1, text="Add", command=create)
    btn1.pack(side="top")
    
    tree2 = ttk.Treeview(frame1)
    
    
    tree2.pack(expand=True, fill="both")
    
    root.mainloop()