";require "../templates/head_jq_bs4.php";echo "";$img_path="..";require "top-link-tkinter.php";require "templates/top_bs4.php";echo "

Python Tkinter Treeview: Tables, Rows and Parent-Child Data

";require "templates/body_start.php";?>

ttk.Treeview displays structured data as a table, a hierarchical tree, or a combination of both. Each item can contain a tree label, optional child items and values displayed across additional columns.

Treeview is useful for displaying database records, file structures, invoices, reports, spreadsheet data and other collections where users need to view or select rows.


Create a Tkinter Treeview 🔝

Treeview belongs to Tkinter's themed widget set, so import ttk.

import tkinter as tkfrom tkinter import ttkroot=tk.Tk()root.geometry('450x250')root.title('Tkinter Treeview - plus2net')tree=ttk.Treeview(root, columns=('id', 'name'), show='headings')tree.grid(row=0, column=0, padx=20, pady=20)tree.heading('id', text='ID')tree.heading('name', text='Name')tree.column('id', width=80, anchor='center')tree.column('name', width=180)tree.insert('', tk.END, values=(1, 'Alex'))tree.insert('', tk.END, values=(2, 'Ravi'))tree.insert('', tk.END, values=(3, 'Ron'))root.mainloop()

This creates a simple two-column table.

Tkinter Treeview displaying column headings and rows

What is ttk?

Tree Column #0 and Additional Columns 🔝

Treeview has a special built-in column named #0. This is the tree column.

It can display:

The columns specified with columns= are additional data columns.

tree=ttk.Treeview(root, columns=('id', 'name'), show='tree headings')tree.heading('#0', text='Category')tree.heading('id', text='ID')tree.heading('name', text='Name')tree.insert('', tk.END, text='Student', values=(1, 'Alex'))

Here:

text='Student'

is displayed in #0, while:

values=(1, 'Alex')

fills the additional columns.

Important: #0 exists even when it is hidden by show='headings'.

Treeview show Option 🔝

show ValueResult
'tree'Displays the tree column #0 but hides headings.
'headings'Displays headings and data columns while hiding #0.
'tree headings'Displays both the tree column and headings. This is the normal default view.
''Hides both the tree column and headings.

Table-Style Treeview

tree['show']='headings'

Hierarchical Treeview

tree['show']='tree headings'
Tkinter Treeview showing expandable hierarchical tree data

Tkinter Treeview Parent and Child Nodes

Insert Rows with insert() 🔝

The basic syntax is:

tree.insert(parent, index, iid=None, text='', values=())

For a top-level row, use an empty string as the parent.

item_id=tree.insert('', tk.END, values=(1, 'Alex'))print(item_id)

insert() returns the new Treeview item identifier, or iid.

You can also provide your own unique item ID.

tree.insert('', tk.END, iid='student_1', values=(1, 'Alex'))
Treeview insert(): Rows, IDs and Child Nodes

Parent-Child Nodes 🔝

A parent item can contain one or more child items.

parent_id=tree.insert('', tk.END, text='Languages', open=True)tree.insert(parent_id, tk.END, text='Python')tree.insert(parent_id, tk.END, text='PHP')tree.insert(parent_id, tk.END, text='JavaScript')

The first argument of insert() determines the parent.

''

means a top-level item.

A real item ID such as:

parent_id

creates a child under that item.

Treeview Parent-Child Nodes

Read Treeview Row Data 🔝

Use item() to get all information stored for an item.

data=tree.item(item_id)print(data)

Read only the row values:

values=tree.item(item_id, 'values')print(values)

Read One Column with set()

If the Treeview has named columns:

name=tree.set(item_id, 'name')print(name)

This is often clearer than relying on a numeric position inside values.

Read Selected Treeview Rows 🔝

selection() returns a tuple containing the selected item IDs.

selected=tree.selection()print(selected)

With one selected row, an example result may look like:

('I001',)

Read the First Selected Row

selected=tree.selection()if selected:    item_id=selected[0]    print(tree.item(item_id, 'values'))

Select Multiple Rows

Use:

tree=ttk.Treeview(root, selectmode='extended')

Then process all selected IDs:

for item_id in tree.selection():    print(tree.item(item_id, 'values'))

<<TreeviewSelect>> Event 🔝

Bind <<TreeviewSelect>> to run a function whenever the selection changes.

def row_selected(event):    tree=event.widget    selected=tree.selection()    if not selected:        return    item_id=selected[0]    print('ID:', item_id)    print('Values:', tree.item(item_id, 'values'))tree.bind('<<TreeviewSelect>>', row_selected)

Using event.widget keeps the callback reusable.

Treeview Selection vs Focus 🔝

Selection and focus are related but different.

MethodMeaning
selection()Returns the item IDs currently selected.
focus()Returns the item that currently has Treeview keyboard focus.

Read the focus item:

focus_item=tree.focus()

Set focus:

tree.focus(item_id)

For normal row-selection logic, use selection(). Do not assume that the focus item is always the same as the selected item.

Move Selection Up or Down 🔝

Buttons to Move UP or DOWN Treeview Row Selection

Do not calculate the next row by adding or subtracting from the iid. Item IDs may be strings, database IDs or non-consecutive values.

Instead, use the actual child order returned by get_children().

def move_selection(step):    rows=tree.get_children()    selected=tree.selection()    if not rows:        return    if not selected:        target=rows[0]    else:        current=selected[0]        position=rows.index(current)        new_position=max(0, min(position+step, len(rows)-1))        target=rows[new_position]    tree.selection_set(target)    tree.focus(target)    tree.see(target)

Buttons:

tk.Button(root, text='Up', command=lambda: move_selection(-1)).grid(row=0, column=0)tk.Button(root, text='Down', command=lambda: move_selection(1)).grid(row=0, column=1)

Update Treeview Row Values 🔝

Updating selected Tkinter Treeview row

Treeview does not provide built-in spreadsheet-style cell editing. However, an application's controls can read a selected row and update its values.

Update with item()

def update_name():    selected=tree.selection()    if not selected:        return    item_id=selected[0]    values=list(tree.item(item_id, 'values'))    values[1]=name_entry.get()    tree.item(item_id, values=values)

This preserves the other column values and changes only the required position.

Update One Named Column with set()

When named columns are used, this is simpler:

tree.set(item_id, 'name', name_entry.get())

For a specific field, set() is often clearer than rebuilding the complete values sequence.

Full Treeview edit example

Delete Treeview Rows 🔝

Delete One Selected Row

selected=tree.selection()if selected:    tree.delete(selected[0])

Delete Multiple Selected Rows

selected=tree.selection()if selected:    tree.delete(*selected)

Delete All Top-Level Items

tree.delete(*tree.get_children())

Deleting a parent also deletes its descendants from the Treeview.

Temporarily Hide an Item with detach()

If an item should disappear without being destroyed:

tree.detach(item_id)

The item still exists and can later be attached again with move().

Read All Treeview Rows 🔝

get_children() without a parent returns the top-level item IDs.

for item_id in tree.get_children():    print(tree.item(item_id, 'values'))

Create a Python List from One Column

names=[]for item_id in tree.get_children():    names.append(tree.set(item_id, 'name'))print(names)

Using column names makes the code easier to understand than relying on positions such as values[1].

Children of a Specific Parent

children=tree.get_children(parent_id)

This returns only the direct children of that parent.

Select, Focus and Show a Row Programmatically 🔝

Select

tree.selection_set(item_id)

Give Keyboard Focus

tree.focus(item_id)

Scroll until the Item Is Visible

tree.see(item_id)

A common combination is:

tree.selection_set(item_id)tree.focus(item_id)tree.see(item_id)

Add to Existing Selection

tree.selection_add(item_id)

Remove from Selection

tree.selection_remove(item_id)

Clear All Selection

tree.selection_remove(tree.selection())

Important Treeview Options 🔝

OptionPurposeExample
columnsDefines additional data column identifiers.columns=('id','name')
displaycolumnsControls which data columns and their display order are visible.displaycolumns=('name','id')
heightRequested number of visible rows.height=10
paddingAdds internal widget padding.padding=5
selectmodeSelection behavior: browse, extended or none.selectmode='extended'
showControls the tree column and headings.show='headings'
styleName of the ttk style applied to the widget.style='Custom.Treeview'
cursorMouse cursor shown over the widget.cursor='hand2'
takefocusControls keyboard focus traversal.takefocus=True
xscrollcommandConnects horizontal scrolling.xscrollcommand=hs.set
yscrollcommandConnects vertical scrolling.yscrollcommand=vs.set

displaycolumns

Suppose Treeview contains:

tree['columns']=('id', 'name', 'class', 'mark')

Display only name and mark:

tree['displaycolumns']=('name', 'mark')

The underlying values still exist; only their display is changed.

Important Tkinter Treeview Methods 🔝

MethodPurpose
insert(parent,index,...)Create and return a new Treeview item.
item(item,...)Read or update item options such as text, values, open and tags.
set(item,column,value)Read or update individual data-column values.
delete(*items)Delete items and their descendants.
detach(*items)Hide items without destroying them.
exists(item)Check whether an item ID exists.
get_children(item=None)Return direct child item IDs.
parent(item)Return an item's parent ID.
index(item)Return its position among siblings.
next(item)Return the next sibling ID.
prev(item)Return the previous sibling ID.
move(item,parent,index)Move or reattach an item.
selection()Return selected item IDs.
selection_set()Replace the current selection.
selection_add()Add items to the current selection.
selection_remove()Remove items from the selection.
selection_toggle()Toggle selection state.
focus()Get or set the focus item.
see(item)Open ancestors if needed and scroll until the item is visible.
column()Read or configure column properties.
heading()Read or configure a column heading.
bbox()Return an item's or cell's bounding box when visible.
identify_row(y)Return the item ID at a y-coordinate.
identify_column(x)Return the display column at an x-coordinate.
identify_region(x,y)Identify whether coordinates are over a heading, separator, tree or cell.
tag_configure()Configure appearance associated with a tag.
tag_bind()Bind events to tagged items.
tag_has()Check which items contain a tag.

Check whether an Item Exists

if tree.exists('student_1'):    print('Item exists')

Find Position among Siblings

position=tree.index(item_id)

Find Previous and Next Siblings

previous_item=tree.prev(item_id)next_item=tree.next(item_id)

Wrap Long Text in Treeview 🔝

Treeview does not automatically wrap long cell text to calculate a different height for each row. One approach is to insert newline characters and increase the Treeview style's common row height.

import tkinter as tkfrom tkinter import ttkimport textwrapdef wrap_text(text, length=20):    return '\n'.join(textwrap.wrap(text, length))root=tk.Tk()style=ttk.Style()style.configure('Treeview', rowheight=60)tree=ttk.Treeview(root, columns=('one', 'two'), show='headings', height=3)tree.heading('one', text='Column 1')tree.heading('two', text='Column 2')tree.column('one', width=120)tree.column('two', width=120)tree.insert('', tk.END, values=(wrap_text('This is long text I want to wrap'), wrap_text('This text is also longer than the column')))tree.insert('', tk.END, values=('No wrap', 'No wrap'))tree.pack(padx=20, pady=20)root.mainloop()
Wrapped long text in Tkinter Treeview cells

The configured rowheight applies to Treeview rows generally; it is not automatically calculated separately for each row.

Add a Vertical Scrollbar 🔝

Vertical scrollbar connected to Tkinter Treeview

Large tables usually require a vertical Scrollbar.

vs=ttk.Scrollbar(root, orient='vertical', command=tree.yview)tree.configure(yscrollcommand=vs.set)tree.grid(row=0, column=0, sticky='nsew')vs.grid(row=0, column=1, sticky='ns')
Treeview with MySQL Records and Scrollbar

Add a Horizontal Scrollbar 🔝

A horizontal scrollbar is useful when the combined column width is wider than the available Treeview area.

tree.column('name', width=250, stretch=False)hs=ttk.Scrollbar(root, orient='horizontal', command=tree.xview)tree.configure(xscrollcommand=hs.set)hs.grid(row=1, column=0, sticky='ew')

stretch=False is useful when you want a column to retain its configured width instead of expanding to consume available space.

Treeview with Excel, Google Sheets and Databases 🔝

Treeview displays the data supplied by your Python program. The source can be a Python collection, database query, spreadsheet, Google Sheet or Pandas DataFrame.

Excel Data with OpenPyXL

Displaying Excel data in Tkinter Treeview

Read Excel rows with OpenPyXL and insert the values into Treeview.

Excel Data in Treeview

Google Sheets Data

Displaying Google Sheets data in Tkinter Treeview

Collect spreadsheet data using pygsheets and display the records through Treeview.

Google Sheets Data in Treeview

MySQL Data

Database records can be displayed as Treeview rows and connected to update, delete and pagination operations.

Display MySQL RecordsMySQL PaginationDelete MySQL RecordsUpdate MySQL Record

Treeview Tutorials and Practical Projects 🔝

After learning the basic widget, choose the next tutorial according to what you want the Treeview to do.

Building and Displaying Treeview Data

Insert Rows and Child NodesParent-Child TreeDynamic Headers and ColumnsImages in Treeview

Styling and Interaction

Treeview StylesCopy Selected RowsSort Treeview with Pandas

Database Applications

Insert MySQL Record and Add RowSelect, Edit and Update ProductSQL Query Window and TreeviewShow Database Record Details

Treeview Projects

Generate Invoice using TreeviewDirectory and File StructureJSON Data ViewerMonthly Report

Build Interactive Tables with Tkinter Treeview

Common Treeview Mistakes 🔝

1. Using selection()[0] without Checking Selection

Avoid:

item_id=tree.selection()[0]

Use:

selected=tree.selection()if selected:    item_id=selected[0]

2. Treating focus() as Selection

focus() and selection() represent different Treeview states.

3. Assuming Item IDs Are Consecutive Numbers

Do not navigate rows by incrementing an iid. Use get_children(), index(), next() or prev().

4. Confusing #0 with Data Columns

#0 is the special tree column. Columns declared with columns= are separate data columns.

5. Expecting Treeview to Edit like a Spreadsheet

Treeview displays values but does not include built-in cell editors. Update values with item() or set(), or create an Entry-based editing interface.

6. Deleting the Treeview Row but Not the Database Record

Treeview and the original data source must be synchronized explicitly.

7. Using Numeric Value Positions Everywhere

This works:

tree.item(item_id, 'values')[1]

but with named columns this is often clearer:

tree.set(item_id, 'name')

8. Calling a Nonexistent selection_clear() Method

Clear the current selection with:

tree.selection_remove(tree.selection())

9. Expecting Automatic Text Wrapping

Treeview does not automatically resize individual rows based on wrapped cell text. Insert line breaks and configure an appropriate row height when needed.

Tkinter Treeview Summary 🔝

What to learn next: If you are building a table, continue with Treeview insert() and database examples. If you are building expandable hierarchical data, continue with parent-child nodes.