Search code examples
tkintertreeviewpython-3.9tabwidget

Automatic resize Treeview (column width & row height) size inside ttk.Notebook


I create a treeview inside a tab from ttk.notebook widget. I followed this description for addapt the size of the treeview table. I saw also the .pack solution, but I will not mix .grid and .pack(). I searched also the web, but couldn't find a solution. The treeview is placed in the frame of the notebook tab, but doesn't fill the available space. I tried also to play with the font size, but this doesn't help a lot. How can I write the code, that the treeview adjust automatic the size of the window.

The example code:

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

root = tk.Tk()
root.title('Treeview demo')
root.geometry('800x400')

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

tabControl = ttk.Notebook(root)
tab1 = ttk.Frame(tabControl)
tabControl.add(tab1, text="Tab 1")

tab2 = ttk.Frame(tabControl)
tabControl.add(tab2, text="Tab 2")

tab1.grid_rowconfigure(0, weight=1) # update change according the answer @acw1668
tab1.grid_columnconfigure(0, weight=1)
tabControl.grid(row=0, column=0, sticky='nsew')

# style the widget
s = ttk.Style()
s.theme_use('clam')
LARGE_FONT = 14
MON_FONTSIZE = 12
s.configure('Treeview.Heading', font=(None, LARGE_FONT), rowheight=int(LARGE_FONT*2.5))
s.configure('Treeview', font=(None, MON_FONTSIZE), rowheight=int(MON_FONTSIZE*2.5))

# define columns
columns = ('first_name', 'last_name', 'email')

tree = ttk.Treeview(tab1, columns=columns, show='headings')

# define headings
tree.heading('first_name', text='First Name')
tree.heading('last_name', text='Last Name')
tree.heading('email', text='Email')
s.configure('Treeview.Heading', background="green3")

# generate sample data
contacts = []
for n in range(1, 100):
    contacts.append((f'first {n}', f'last {n}', f'email{n}@example.com'))

# add data to the treeview AND tag the row color
i = 1
for contact in contacts:
    i += 1
    if i%2:
        tree.insert('', tk.END, values=contact, tags = ('oddrow',))
    else:
        tree.insert('', tk.END, values=contact, tags = ('evenrow',))
    


def item_selected(event):
    for selected_item in tree.selection():
        item = tree.item(selected_item)
        record = item['values']
        # show a message
        showinfo(title='Information', message=','.join(record))


tree.bind('<<TreeviewSelect>>', item_selected)

tree.grid(row=0, column=0, sticky='nsew')

# add a scrollbar
scrollbar = ttk.Scrollbar(tab1, orient=tk.VERTICAL, command=tree.yview)
tree.configure(yscroll=scrollbar.set)
scrollbar.grid(row=0, column=1, sticky='ns')

# style row colors
tree.tag_configure('oddrow', background='lightgrey')
tree.tag_configure('evenrow', background='white')

# run the app
root.mainloop()

Result should fill the whole available space: tkinter window with treeview inside tab

Updated result, without any change: enter image description here


Solution

  • If you want the treeview widget to fill the available space, you need to:

    • allocate the available vertical space to row 0 by tab1.grid_rowconfigure(0, weight=1)
    • allocate the available horizontal space to column 0 by tab1.grid_columnconfigure(0, weight=1)

    Result:

    enter image description here

    Or you can use .pack() instead of .grid() on tree and scrollbar widgets:

    scrollbar.pack(side='right', fill='y')
    tree.pack(side='left', fill='both', expand=1)