Of course! The tkinter.ttk.Treeview widget is one of the most powerful and versatile widgets in the Tkinter library. It's used to display data in a hierarchical, tree-like structure, similar to a file explorer or an outliner.

This guide will cover everything you need to know to start using the Treeview widget effectively, from basic creation to advanced features like sorting, editing, and styling.
Basic Treeview Structure
A Treeview is built from three main components:
- The
TreeviewWidget: The main container. - Columns: Define the headers for the data columns (like "Name", "Size", "Type" in a file explorer).
- Items (or Rows): The individual entries in the tree. Each item has a unique string identifier (an IID) and can contain data for each column.
- Children: Items can have child items, creating the hierarchical structure.
Creating a Simple Treeview
Let's start with the most basic example: creating a Treeview with one column and a few top-level items.
import tkinter as tk
from tkinter import ttk
# --- Create the main window ---
root = tk.Tk()"Simple Treeview")
root.geometry("300x200")
# --- Create the Treeview widget ---
# The first column is special and doesn't need a heading text.
# We give it a heading of just a space to make it look clean.
tree = ttk.Treeview(root, columns=('Name',), show='tree headings')
# --- Define the columns ---
tree.column('#0', width=0, stretch=False) # Hide the default first column
tree.column('Name', anchor='w', width=200)
tree.heading('#0', text='', anchor='w')
tree.heading('Name', text='File Name', anchor='w')
# --- Add data (items) ---
# The first argument is the parent item. For top-level items, use ''.
# The second argument is the item's unique ID (IID).
# The 'text' argument populates the first visible column.
# The 'values' argument is a tuple of data for the other columns.
item1 = tree.insert('', 'end', text='Folder 1', values=('Important Stuff',))
item2 = tree.insert('', 'end', text='Folder 2', values=('Misc',))
# --- Add child items ---
tree.insert(item1, 'end', text='document.txt', values=('1.2 KB',))
tree.insert(item1, 'end', text='image.png', values=('350 KB',))
tree.insert(item2, 'end', text='notes.txt', values=('0.5 KB',))
# --- Pack the widget to make it visible ---
tree.pack(pady=10, padx=10, fill='both', expand=True)
# --- Start the main loop ---
root.mainloop()
Explanation:

ttk.Treeview(root, columns=('Name',), show='tree headings'): Creates the widget.columns: A tuple of strings for the column names.show: This is a crucial option.'tree': Shows the tree column (the one with the +/- icons).'headings': Shows the column headers.'tree headings': Shows both.'all': The default, shows everything.- Hides everything.
tree.column()andtree.heading(): Configure the appearance and text of the columns.tree.insert(): Adds an item to the tree.parent: The ID of the parent item. means it's a top-level item.index: Where to insert the item ('end'for the last position).text: The text displayed in the first column (the tree column).values: A tuple containing the data for the other columns defined incolumns.
Working with Selections
You often need to know which item the user has selected.
# ... (inside the main window from the previous example) ...
def item_selected(event):
"""
Handles selection of an item in the tree.
"""
selected_item_id = tree.selection()[0] # Get the first selected item's ID
item_data = tree.item(selected_item_id) # Get the item's data
print(f"Selected Item ID: {selected_item_id}")
print(f"Item Text: {item_data['text']}")
print(f"Item Values: {item_data['values']}")
print("-" * 20)
# Bind the selection event to our function
tree.bind('<<TreeviewSelect>>', item_selected)
# --- Add a button to demonstrate ---
def print_selection():
selected = tree.selection()
if selected:
print(f"Button clicked on item: {tree.item(selected[0])['text']}")
else:
print("No item selected!")
btn = ttk.Button(root, text="Print Selection", command=print_selection)
btn.pack(pady=5)
# ... (root.mainloop()) ...
Key Methods:
tree.selection(): Returns a tuple of the IDs of all selected items.tree.item(item_id): Returns a dictionary containing the item's data:{'text': '...', 'image': ..., 'values': ('...'), 'tags': [...]}.tree.focus(): Returns the ID of the item that currently has the keyboard focus.
Advanced Features
a. Hierarchical Data (Folders and Files)
The real power of Treeview is its hierarchy. We can easily build a file explorer-like structure.
# ... (inside the main window) ...
# Clear previous items
tree.delete(*tree.get_children())
# Define the data structure
data = {
'C:': {
'Program Files': {'app1.exe': (), 'app2.exe': ()},
'Users': {'john': {'Documents': ('report.docx',)}, 'jane': ()},
'Windows': {'System32': ()}
}
}
def insert_data(parent, data_dict):
"""Recursively inserts data into the tree."""
for key, value in data_dict.items():
if value: # It's a folder
item_id = tree.insert(parent, 'end', text=key, values=('',))
insert_data(item_id, value)
else: # It's a file
tree.insert(parent, 'end', text=key, values=('File',))
# Insert the data starting from the root
insert_data('', data['C:'])
b. Adding Icons
You can associate images with items to make them more visually appealing. You need to create an Image object first.

from PIL import Image, ImageTk # Pillow library
# ... (inside the main window) ...
# Create PhotoImage objects for icons
# Note: You need to have 'folder.png' and 'file.png' in the same directory
# or provide the full path.
try:
folder_icon = ImageTk.PhotoImage(Image.open("folder.png"))
file_icon = ImageTk.PhotoImage(Image.open("file.png"))
except FileNotFoundError:
print("Icon files not found. Using default icons.")
# Fallback to default icons if images are not found
folder_icon = tk.PhotoImage(data="iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mNkYPhfz0AEYwqIAAChwY4aQcAEAIQwBgCwB4AfBOAB/gAAAAAElFTkSuQmCC")
file_icon = tk.PhotoImage(data="iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mNkYPhfz0AEYwqIAAChwY4aQcAEAIQwBgCwB4AfBOAB/gAAAAAElFTkSuQmCC")
# ... (inside the insert_data function) ...
def insert_data(parent, data_dict):
for key, value in data_dict.items():
if value: # It's a folder
item_id = tree.insert(parent, 'end', text=key, image=folder_icon, values=('',))
insert_data(item_id, value)
else: # It's a file
tree.insert(parent, 'end', text=key, image=file_icon, values=('File',))
c. Sorting Columns
A very common request is to sort the data when a column header is clicked.
# --- Add a sorting variable to keep track of the sort order ---
sort_column = None
sort_reverse = False
def sort_treeview(tv, col, reverse):
"""Sorts a treeview widget's contents."""
l = [(tv.set(k, col), k) for k in tv.get_children('')]
# Try to sort numerically if possible
try:
l.sort(key=lambda t: float(t[0]), reverse=reverse)
except ValueError:
# If not, sort alphabetically
l.sort(reverse=reverse)
# Rearrange items in sorted order
for index, (val, k) in enumerate(l):
tv.move(k, '', index)
# Update the sort order for the next click
sort_reverse = not sort_reverse
# --- Bind the heading to the sort function ---
tree.heading('Name', command=lambda: sort_treeview(tree, 'Name', sort_reverse))
d. Editing Data
You can allow users to edit the text of an item directly.
# --- Add a double-click event to edit an item ---
def on_double_click(event):
# Get the item that was double-clicked
item_id = tree.identify('item', event.x, event.y)
if item_id:
# Start editing the first column (text)
tree.item(item_id, text="Editing...") # Optional: change text temporarily
tree.set(item_id, 'Name', 'New Value') # Set the value in the 'Name' column
# Note: Direct text editing requires more complex code or a custom Entry widget.
# This example just shows how to change the value programmatically.
# A true "in-place" editor is more involved.
tree.bind('<Double-1>', on_double_click)
Complete Example: A File Explorer
Here is a complete, runnable example that combines many of these features: hierarchy, icons, and sorting.
import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk
# --- Setup ---
root = tk.Tk()"File Explorer Example")
root.geometry("600x400")
# --- Icons (using simple colored placeholders) ---
# In a real app, you'd load .png or .ico files
folder_img = tk.PhotoImage(width=16, height=16)
file_img = tk.PhotoImage(width=16, height=16)
# Create a simple folder icon (blue square)
folder_img.put("#0000FF", to=(0, 0, 15, 15))
# Create a simple file icon (gray square)
file_img.put("#808080", to=(0, 0, 15, 15))
# --- Data ---
file_structure = {
'Projects': {
'Website': {'index.html': (), 'styles.css': (), 'script.js': ()},
'App': {'main.py': (), 'utils.py': (), 'data.json': ()},
'Notes': {'ideas.txt': (), 'todo.md': ()}
},
'Documents': {
'Resume.pdf': (),
'Cover Letter.docx': ()
},
'Pictures': {'vacation.jpg': (), 'family.png': ()}
}
# --- Treeview ---
columns = ('Type', 'Size')
tree = ttk.Treeview(root, columns=columns, show='tree headings')
# --- Columns ---
tree.column('#0', anchor='w', width=250)
tree.column('Type', anchor='center', width=100)
tree.column('Size', anchor='e', width=100)
tree.heading('#0', text='Name', anchor='w', command=lambda: sort_by_column(tree, '#0', False))
tree.heading('Type', text='Type', anchor='center', command=lambda: sort_by_column(tree, 'Type', False))
tree.heading('Size', text='Size', anchor='e', command=lambda: sort_by_column(tree, 'Size', False))
# --- Scrollbar ---
scrollbar = ttk.Scrollbar(root, orient="vertical", command=tree.yview)
tree.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side='right', fill='y')
tree.pack(side='left', fill='both', expand=True)
# --- Functions ---
def insert_data(parent, data_dict):
for key, value in data_dict.items():
if value: # It's a folder
item_id = tree.insert(parent, 'end', text=key, image=folder_img, values=('Folder', ''))
insert_data(item_id, value)
else: # It's a file
# Generate a fake size
size = f"{hash(key) % 1000 + 100} KB"
tree.insert(parent, 'end', text=key, image=file_img, values=('File', size))
def sort_by_column(tv, col, reverse):
l = [(tv.set(k, col), k) for k in tv.get_children('')]
l.sort(reverse=reverse)
# Handle numeric sort for 'Size' column
if col == 'Size':
l.sort(key=lambda t: float(t[0].split()[0]), reverse=reverse)
for index, (val, k) in enumerate(l):
tv.move(k, '', index)
# Reverse sort order for next click
tree.heading(col, command=lambda: sort_by_column(tv, col, not reverse))
# --- Populate the tree ---
insert_data('', file_structure)
# --- Mainloop ---
root.mainloop()
This comprehensive guide should give you a solid foundation for using the tkinter.ttk.Treeview widget in your Python applications. Experiment with these examples to build more complex and interactive data displays.
