The Tkinter ttk.Treeview.insert() method adds an item to a Treeview. The new item can be a top-level row or a child of another item, so the same method works for both table-style and hierarchical data.

'' for a top-level item. To create a child, pass the parent's iid as the first argument to insert().tree.insert(parent, index, iid=None, **options)
| Argument | Meaning |
|---|---|
parent | Parent iid. Use '' for a top-level item. |
index | Position among the parent's children. Use 0, another integer or 'end'. |
iid | Optional unique item identifier. Treeview creates one automatically when omitted. |
text | Text shown in the Treeview's #0 tree column. |
values | Data displayed in the additional configured columns. |
open | Whether a parent item starts expanded. |
tags | Tags associated with the item for styling or events. |
The method returns the iid of the newly created item.
If the Treeview is being used only as a table and no parent-child hierarchy is needed, the tree column can be hidden with show='headings'.
import tkinter as tk
from tkinter import ttk
root=tk.Tk()
root.geometry('520x250')
columns=('id', 'name', 'class', 'mark', 'gender')
tree=ttk.Treeview(root, columns=columns, show='headings', selectmode='browse')
tree.heading('id', text='ID')
tree.heading('name', text='Name')
tree.heading('class', text='Class')
tree.heading('mark', text='Mark')
tree.heading('gender', text='Gender')
tree.column('id', width=50, anchor='center')
tree.column('name', width=120)
tree.column('class', width=90, anchor='center')
tree.column('mark', width=70, anchor='center')
tree.column('gender', width=90, anchor='center')
tree.pack(padx=20, pady=20, fill='x')
root.mainloop()
Use an empty string as the parent to add a top-level row.
tree.insert('', 'end', values=(1, 'Alex', 'Four', 78, 'Male'))
The first argument:
''
represents Treeview's invisible root, so the new record becomes a top-level item.
Every Treeview item has a unique identifier called an iid.
item_id=tree.insert('', 'end', values=(1, 'Alex', 'Four', 78, 'Male'))
print(item_id)
insert() returns the generated iid. This identifier can later be used with methods such as item(), delete(), move() and see().
tree.insert('', 'end', iid='student_1', values=(1, 'Alex', 'Four', 78, 'Male'))
The Treeview iid and an application's record ID do not have to be the same value.
student_id=36
item_id=tree.insert('', 'end', values=(student_id, 'King', 'Five', 45, 'Male'))
Here student_id is application data, while item_id is the Treeview identifier.
tree.insert('', 'end', values=(2, 'Ravi', 'Five', 82, 'Male'))
tree.insert('', 0, values=(2, 'Ravi', 'Five', 82, 'Male'))
tree.insert('', 1, values=(3, 'Raju', 'Four', 75, 'Male'))
The index is relative to the other children of the same parent.
We can collect data using Entry, Combobox, Radiobutton and a Button, then insert the new row.
import tkinter as tk
from tkinter import ttk
root=tk.Tk()
root.geometry('600x420')
root.title('Treeview insert() - plus2net')
columns=('id', 'name', 'class', 'mark', 'gender')
tree=ttk.Treeview(root, columns=columns, show='headings', selectmode='browse')
tree.grid(row=0, column=0, columnspan=5, padx=20, pady=20)
headings=('ID', 'Name', 'Class', 'Mark', 'Gender')
for column, heading in zip(columns, headings):
tree.heading(column, text=heading)
tree.column(column, width=100, anchor='center')
tree.insert('', 'end', values=(1, 'Alex', 'Four', 78, 'Male'))
next_id=2
def add_data():
global next_id
name=name_entry.get().strip()
student_class=class_combo.get()
mark=mark_entry.get().strip()
gender=gender_var.get()
item_id=tree.insert('', 'end', values=(next_id, name, student_class, mark, gender))
tree.selection_set(item_id)
tree.focus(item_id)
tree.see(item_id)
next_id+=1
name_entry.delete(0, tk.END)
mark_entry.delete(0, tk.END)
class_combo.set('')
status_var.set('Data added')
name_entry.focus_set()
root.after(3000, lambda: status_var.set(''))
tk.Label(root, text='Name').grid(row=1, column=0)
name_entry=tk.Entry(root, width=14)
name_entry.grid(row=2, column=0, padx=5)
tk.Label(root, text='Class').grid(row=1, column=1)
class_combo=ttk.Combobox(root, values=('Three', 'Four', 'Five'), state='readonly', width=10)
class_combo.grid(row=2, column=1, padx=5)
tk.Label(root, text='Mark').grid(row=1, column=2)
mark_entry=tk.Entry(root, width=8)
mark_entry.grid(row=2, column=2, padx=5)
gender_var=tk.StringVar(value='Female')
tk.Radiobutton(root, text='Male', variable=gender_var, value='Male').grid(row=2, column=3)
tk.Radiobutton(root, text='Female', variable=gender_var, value='Female').grid(row=2, column=4)
tk.Button(root, text='Add Record', command=add_data).grid(row=3, column=0, columnspan=5, pady=15)
status_var=tk.StringVar()
tk.Label(root, textvariable=status_var).grid(row=4, column=0, columnspan=5)
root.mainloop()
After inserting the row, this part selects it, gives it focus and scrolls it into view if required:
tree.selection_set(item_id)
tree.focus(item_id)
tree.see(item_id)
The earlier example demonstrates insertion. In an actual form, validate the input before adding a record.
def add_data():
global next_id
name=name_entry.get().strip()
student_class=class_combo.get()
mark_text=mark_entry.get().strip()
gender=gender_var.get()
if not name:
status_var.set('Enter student name')
return
if not student_class:
status_var.set('Select a class')
return
try:
mark=int(mark_text)
except ValueError:
status_var.set('Mark must be an integer')
return
if not 0 <= mark <= 100:
status_var.set('Mark must be from 0 to 100')
return
item_id=tree.insert('', 'end', values=(next_id, name, student_class, mark, gender))
next_id+=1
Validation prevents incomplete or invalid records from being displayed in the Treeview.
Treeview is not limited to flat tables. An item can be inserted under another item's iid.
parent_id=tree.insert('', 'end', text='Alex', values=('Four', 78, 'Male'), open=True)
child_id=tree.insert(parent_id, 'end', text='Ravi', values=('Five', 82, 'Male'))
The important difference is the first argument:
tree.insert('', 'end', ...) # top-level parent
tree.insert(parent_id, 'end', ...) # child of parent_id

For hierarchical data, do not hide the tree portion with show='headings'. Instead use:
tree=ttk.Treeview(root, columns=('class', 'mark', 'gender'), show='tree headings')
The special #0 column contains the hierarchy, item text and expand/collapse indicator.
tree.heading('#0', text='Student')
tree.column('#0', width=150)
Additional data is placed in the configured columns.
tree.heading('class', text='Class')
tree.heading('mark', text='Mark')
tree.heading('gender', text='Gender')
show='headings' is suitable for a flat table. For an interactive parent-child hierarchy, keep the tree portion visible so users can see indentation and expand or collapse parent nodes.Use selection() to obtain the selected Treeview item.
selected=tree.selection()
if selected:
parent_id=selected[0]
tree.insert(parent_id, 'end', text='New Child')
With selectmode='browse', only one item can be selected by the user, so the first selected iid is used.
Treeview supports multiple hierarchy levels. If the application should allow children only under top-level parents, check the selected item's parent.
selected=tree.selection()
if selected:
parent_id=selected[0]
if tree.parent(parent_id) == '':
tree.insert(parent_id, 'end', text='New Child')
This example provides separate buttons for adding top-level parent rows and child rows. The Add Child button becomes available when a top-level parent is selected.
import tkinter as tk
from tkinter import ttk
root=tk.Tk()
root.geometry('600x500')
root.title('Treeview Parent and Child - plus2net')
columns=('class', 'mark', 'gender')
tree=ttk.Treeview(root, columns=columns, show='tree headings', selectmode='browse')
tree.grid(row=0, column=0, columnspan=4, padx=20, pady=20, sticky='nsew')
tree.heading('#0', text='Name')
tree.heading('class', text='Class')
tree.heading('mark', text='Mark')
tree.heading('gender', text='Gender')
tree.column('#0', width=160)
tree.column('class', width=90, anchor='center')
tree.column('mark', width=80, anchor='center')
tree.column('gender', width=90, anchor='center')
tree.insert('', 'end', text='Alex', values=('Four', 78, 'Male'), open=True)
def read_form():
name=name_entry.get().strip()
student_class=class_combo.get()
mark_text=mark_entry.get().strip()
gender=gender_var.get()
if not name or not student_class:
status_var.set('Enter name and select class')
return None
try:
mark=int(mark_text)
except ValueError:
status_var.set('Enter a valid mark')
return None
if not 0 <= mark <= 100:
status_var.set('Mark must be from 0 to 100')
return None
return name, student_class, mark, gender
def clear_form():
name_entry.delete(0, tk.END)
mark_entry.delete(0, tk.END)
class_combo.set('')
name_entry.focus_set()
def add_parent():
data=read_form()
if data is None:
return
name, student_class, mark, gender=data
item_id=tree.insert('', 'end', text=name, values=(student_class, mark, gender), open=True)
tree.selection_set(item_id)
tree.focus(item_id)
tree.see(item_id)
status_var.set('Parent added')
clear_form()
def add_child():
selected=tree.selection()
if not selected:
status_var.set('Select a parent row')
return
parent_id=selected[0]
if tree.parent(parent_id) != '':
status_var.set('Select a top-level parent')
return
data=read_form()
if data is None:
return
name, student_class, mark, gender=data
child_id=tree.insert(parent_id, 'end', text=name, values=(student_class, mark, gender))
tree.item(parent_id, open=True)
tree.selection_set(child_id)
tree.focus(child_id)
tree.see(child_id)
status_var.set('Child added')
clear_form()
def update_child_button(event=None):
selected=tree.selection()
enabled=bool(selected and tree.parent(selected[0]) == '')
child_button.config(state=tk.NORMAL if enabled else tk.DISABLED)
tk.Label(root, text='Name').grid(row=1, column=0)
name_entry=tk.Entry(root, width=15)
name_entry.grid(row=2, column=0, padx=5)
tk.Label(root, text='Class').grid(row=1, column=1)
class_combo=ttk.Combobox(root, values=('Three', 'Four', 'Five'), state='readonly', width=10)
class_combo.grid(row=2, column=1, padx=5)
tk.Label(root, text='Mark').grid(row=1, column=2)
mark_entry=tk.Entry(root, width=8)
mark_entry.grid(row=2, column=2, padx=5)
gender_var=tk.StringVar(value='Female')
tk.Radiobutton(root, text='Male', variable=gender_var, value='Male').grid(row=2, column=3)
tk.Radiobutton(root, text='Female', variable=gender_var, value='Female').grid(row=2, column=4)
tk.Button(root, text='Add Parent', command=add_parent).grid(row=3, column=0, columnspan=2, pady=15)
child_button=tk.Button(root, text='Add Child', command=add_child, state=tk.DISABLED)
child_button.grid(row=3, column=2, columnspan=2, pady=15)
status_var=tk.StringVar()
tk.Label(root, textvariable=status_var).grid(row=4, column=0, columnspan=4)
tree.bind('<<TreeviewSelect>>', update_child_button)
root.mainloop()
When a child is inserted, this opens the parent and makes the new child visible:
tree.item(parent_id, open=True)
tree.see(child_id)
These methods answer different questions.
| Method | Meaning |
|---|---|
tree.selection() | Returns the currently selected item iid values. |
tree.focus() | Returns the item that currently has keyboard/widget focus. |
When responding to:
'<<TreeviewSelect>>'
use:
selected=tree.selection()
to determine which items are selected.
selection() when your logic depends on selection.The examples above modify only the GUI. When Treeview represents database records, the usual workflow is:
Top-level item:
tree.insert('', 'end', ...)
Child item:
tree.insert(parent_id, 'end', ...)
This is usually enough:
item_id=tree.insert('', 'end', values=data)
Treeview generates a unique iid and returns it.
If custom iids are supplied, each one must be unique.
For a flat table:
show='headings'
For visible hierarchical data:
show='tree headings'
The text option belongs to the special #0 tree column. If the tree portion is hidden, use values for the visible data columns.
Use:
selected=tree.selection()
when the operation depends on the selected row.
A student's name or mark is better collected with Entry. A Text widget is designed for multi-line input.
Validate required fields and numeric values before inserting them into the Treeview.
Treeview.insert() changes only the GUI widget. It does not insert records into MySQL, SQLite or another data source.
Use:
tree.item(parent_id, open=True)
tree.see(child_id)
when the newly added child should immediately become visible.
Treeview.insert() to add items to a Treeview.'' creates a top-level item.'end' to append an item.0 to insert an item first.insert() returns the iid of the newly created item.values for additional data columns.text for the special #0 tree column.show='headings' is suitable for a flat table.show='tree headings' is suitable for visible parent-child hierarchies.selection() when logic depends on selected items.focus() represents the focus item and should not automatically be treated as the selection.<<TreeviewSelect>> to react when the selection changes.parent(iid) to determine whether an item is top-level or nested.item(parent_id, open=True) to expand a parent.see(iid) to ensure a newly inserted item is visible.Treeview.insert() updates the GUI only; database storage is a separate operation.Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.