10. Tree Widgets
Tree widgets are designed to represent hierarchical data structures, such as file systems or organizational charts, where items can have parent-child relationships.
QTreeWidgetis a convenience class with built-in item management, allowing you to create and manipulate tree nodes directly.QTreeViewfollows Qt’s model/view architecture and works with a separate model. This enables dynamic updates and efficient handling of large datasets.QColumnViewdisplays a model using multipleQListViews, one for each level of the hierarchy.
Their common features include expandable and collapsible nodes, drag-and-drop support, item editing, checkable items, and multi-column display for detailed item properties.
10.1 QTreeWidget
QTreeWidget is a convenience class that provides a standard tree widget with a classic item-based interface.[^1] It automatically creates and manages its own built-in model behind the scenes and uses QTreeWidgetItems as its tree nodes. Each QTreeWidgetItem represents a node in the tree. For top-level items, parent is the widget itself.
![]() |
Your finance application needs a settings screen with configuration options grouped into categories such as General and Notifications. |
To represent hierarchical configuration settings using a QTreeWidget:

-
Create a
QTreeWidgetobject and set its column count. The default is 1 column, but for name-value pairs you need 2 columns. The data itself is stored in a nested Python tuple where each node follows the pattern(name, value, children):name- a string label.value- the setting’s value (string, bool, etc.)children- a list of child tuples in the same format, or[]for leaf nodes. The root node of the structure is ‘Application Settings’, which contains two category children (‘General’ and ‘Notifications’), each with leaf nodes representing the actual settings.
Populate the tree using a recursive
build_tree()helper method. This method takes a parent (either the tree widget itself or aQTreeWidgetItem) and the node data as parameters. It unpacks the tuple, creates aQTreeWidgetItem, and recursively adds any children. Qt item flags are used to make only the leaf nodes editable.Save the changes to the configuration. When the user edits a value, the
itemChanged()signal is emitted. Connect it to a slot that saves the updates configuration (here simulated).
When you run the application, you see an editable tree widget displaying the configuration hierarchy.

10.2 QTreeView
A QTreeView implements a tree representation of items from a model as part of Qt’s model-view architecture. Unlike QTreeWidget, it does not manage its own model so you need to supply one explicitly.[^2]
![]() |
You need to display your monthly budget broken down by category, with columns for the budgeted amount and the account is paid from. |
To show a budget breakdown grouped by category using a QTreeView:

Create and populate the model. Use a
QStandardItemModelwithQStandardItemobjects as tree nodes. Because the data has only two levels (category and subcategory) you can build the model directly in the main window’s__init__()without recursion.QStandardItemModelprovides an invisible root item (accessed viainvisibleRootItem()) that serves as the parent for top-level items. Add category items to the invisible root, then add subcategory items to their respective category parents.Create the
QTreeView.Set the model on the view with
setModel().
QStandardItemModel sits halfway between the fully hidden default tree model of QTreeWidget and a fully custom QAbstractItemModel subclas (covered in chapters 22 - 26):
QTreeWidget- model is completely hidden and you work only withQTreeWidgetItemobjects.QStandardItemModel- model is explicit and you own it, but it is still item-based (QStandardItemobjects), so you don’t need to implement the model interface yourself.QAbstractItemModel- you implement the model from scratch, mapping directly to your own data structures.
QStandardItemModel gives you the flexibility of the model/view split without the overhead of subclassing QAbstractItemModel. The tradeoff is that it stores data in QStandardItem objects internally, which can bel less efficient than a custom model.

10.3 Lazy-loading Trees
Lazy loading is a technique used to defer initialization of an object until it is needed[^3]. In Qt’s model-view architecture it is useful for fetching and displaying large lists, tables or trees with large or deep hierarchies, such as file systems: instead of loading every subdirectory at startup, child nodes are populated only when the user expands a parent node. This keeps the application responsive and reduces initial memory and CPU usage.
![]() |
In your application, you need to let users browse the file system (for example, to locate a bank statement file or choose a folder for exported folders) without freezing the UI. You implement lazy loading in a |
To implement lazy loading with a QTreeView:

Create a
QTreeViewand aQStandardItemModel. Add a single top-level item representing the home directory (Path.home()). Attach a single placeholder child row to this item. The placeholder ensures the expand arrow is visible even though the real children have not yet been loaded.Connect the
expanded()signal of the tree view to a slot. This signal is emitted every time the user clicks the expand arrow on a node.In the
get_subdirectories()slot, check if the expanded item still contains the placeholder. If it does, remove the placeholder, read the real subdirectories from the filesystem usingPath.iterdir(), and create a newQStandardItemfor each subdirectory. Each new item also receives its own placeholder child so that it can be expanded later. Finally, add the new items to the parent.
When you run the application, you see a tree view that initially shows only the home folder. As you expand each directory, its subdirectories are loaded on demand.

The placeholder technique shown above is a shortcut when you are still using QStandardItemModel. For larger trees or production code, Qt provides a built-in mechanism: the canFetchMore() and fetchMore() methods of QAbstractItemModel which we explore in Chapter 24.
