pythonpandastkintertreeviewttk

How to make the ttk treeview not show extra empty columns?


I am building an app with tkinter and running into some annoying issues.

When I load my data into the ttk treeview, I see that there are always some additional columns on the right side of my treeview which are empty. I realized for a bigger data set there are many more columns which are empty (actual data is loaded correctly). I want to get rid of these extra columns or know the source of this. I have attached a code sample below to show the issue.

I would also like to create a column selection functionality but unless the above issue is solved I don't feel like moving forward with it. Is there a simple solution to get rid of the empty columns? is column selection possible out of the box? The idea is to have a little bit excel kind of functionality but not too elaborate.

import pandas as pd
import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showinfo

root = tk.Tk()
root.title('Treeview demo')
root.geometry('620x200')

data = {'Name':['Tom', 'nick', 'krish', 'jack', 'mack', 'tack', 'crack', 'lack'], 
        'Age':[20, 21, 19, 18, 20, 21, 19, 18]}

df = pd.DataFrame(data)

tree = ttk.Treeview(root, columns=df.columns, show='headings')
scrollbar_y = ttk.Scrollbar(root, command=tree.yview)
scrollbar_x = ttk.Scrollbar(root, command=tree.xview,
                                    orient=tk.HORIZONTAL)
tree.config(xscrollcommand=scrollbar_x.set, yscrollcommand=scrollbar_y.set)
scrollbar_y.pack(fill=tk.Y, side=tk.RIGHT)
scrollbar_x.pack(fill=tk.X, side=tk.BOTTOM)
tree.pack(fill="both", expand=True)

df.dropna(axis=1, how='all', inplace=True)

df.columns = [str(x)[:50] for x in df.columns]
df = df.reset_index(drop=True)

print("all cols : ", df.columns)

print(df.columns)

# display the data in the treeview.
df_list = list(df.columns)
df_reset = df.to_numpy().tolist()

print("No of columns ", len(df_list))

tree["columns"] = df.columns

for i in range(len(df_list)):
    col = df_list[i]
    tree.column(i, anchor='c')
    tree.heading(i, text=col)

j = 0
for dt in df_reset:
    v = [r for r in dt]
    print("v ", v)
    tree.insert('', 'end', iid=j, values=v)
    j += 1
print("Total rows : ", j)

root.mainloop()

enter image description here

Thanks for your suggestions in advance!

Edit: fixed the typo in instantiation of treeview to df.columns as suggested. In the real code I Instantiate an empty tree and later on populate it with content and set columns using

tree["columns"] = df.columns.

Solution

  • If you print out tree["columns"] after tree["columns"] = df.columns, you will get:

    ("Index(['Name',", "'Age'],", "dtype='object')")
    

    So you actually configure the treeview to have three columns instead of two.

    You need to convert df.columns to list:

    tree["columns"] = df.columns.to_list()
    

    Or simply use df_list (result of converting df.columns to list) instead of df.columns:

    tree["columns"] = df_list
    

    And the result of your code:

    enter image description here