How to use QTreeWidget() in PySide2
GOAL
To create tree widget in my GUI program with PySide2.
Environment
Windows 10
Python 3.8.7
PySide2 5.15.2
Related Classes
Reference: PySide.QtGui / Qt Widgets C++ Classes
- QTreeWidget: Tree view that uses a predefined tree model
- QTreeWidgetItem: Item for use with the QTreeWidget convenience class
- QTreeWidgetItemIterator: Way to iterate over the items in a QTreeWidget instance
Examples
I created sample window and 4 types of tree widgets and 2 functions. The below is the template.
import sys from PySide2.QtWidgets import * class MyMainWindow(QMainWindow): def __init__(self, parent=None): super(MyMainWindow, self).__init__(parent) self._generateUI() #self._simple_tree_widget() self._tree_widget1() def _generateUI(self): main_widget = QWidget() main_layout = QVBoxLayout() main_widget.setLayout(main_layout) self.setCentralWidget(main_widget) self.tree_widget = QTreeWidget() main_layout.addWidget(self.tree_widget) def _tree_widget1(self): ... def _tree_widget2(self): ... def launch(): app = QApplication.instance() if not app: app = QApplication(sys.argv) widget = MyMainWindow() widget.show() app.exec_() launch()
Example 1. Simple tree widget
def _tree_widget1(self): self.tree_widget.setHeaderLabels(["header"]) tree_widget_item1 = QTreeWidgetItem(["item1"]) tree_widget_item1.addChild(QTreeWidgetItem(["item1_2"])) tree_widget_item2 = QTreeWidgetItem(["item2"]) tree_widget_item2.addChild(QTreeWidgetItem(["item2_2"])) self.tree_widget.addTopLevelItem(tree_widget_item1) self.tree_widget.addTopLevelItem(tree_widget_item2)
Example 2. Item with column
def _tree_widget2(self): headers = ["header1", "header2", "header3"] self.tree_widget.setHeaderLabels(headers) tree_widget_item1 = QTreeWidgetItem(["items1_col1", "items1_col2", "items1_col3"]) tree_widget_item1.addChild(QTreeWidgetItem(["items1_2_col1", "items1_2_col2", "items1_2_col3"])) self.tree_widget.addTopLevelItem(tree_widget_item1)
Example 3. Deep hierarchy tree with for loop
I used dict and for loop. Please let me know if you have any good implementation.
def _tree_widget3(self): self.tree_widget.setHeaderHidden(True) # define items as dictionary children_level1 = ["child1", "child2", "child3"] children_level2 = {"child1":["child1_1", "child1_2"], "child2":["child2_1"], "child3":["child3_1", "child3_2", "child3_3"]} children_level3 = {"child1_2":["child1_2_1", "child1_2_3"], "child3_1":["child3_1_1"]} for child1 in children_level1: item1 = QTreeWidgetItem([child1]) self.tree_widget.addTopLevelItem(item1) if child1 in children_level2: for child2 in children_level2[child1]: item2 = QTreeWidgetItem([child2]) item1.addChild(item2) if child2 in children_level3: for child3 in children_level3[child2]: item3 = QTreeWidgetItem([child3]) item2.addChild(item3)
Example 4. Use widget as item
I create custom widget to add a tree widget.
class MyItemWidget(QWidget): def __init__(self, id_str=0, parent=None): super(MyItemWidget, self).__init__(parent) main_layout = QVBoxLayout() self.setLayout(main_layout) label = QLabel("test_label" + id_str) button = QPushButton("test_button" + id_str) main_layout.addWidget(label) main_layout.addWidget(button) self.setAutoFillBackground(True)
Then set item and set widget to the item and column.
def _tree_widget4(self): self.tree_widget.setHeaderHidden(True) tree_widget_item1 = QTreeWidgetItem(["parent"]) tree_widget_item1_1 = QTreeWidgetItem(["child1"]) tree_widget_item1_2 = QTreeWidgetItem(["child2"]) tree_widget_item1.addChild(tree_widget_item1_1) tree_widget_item1.addChild(tree_widget_item1_2) self.tree_widget.addTopLevelItem(tree_widget_item1) child_widget1 = MyItemWidget(id_str='1') child_widget2 = MyItemWidget(id_str='1_1') child_widget3 = MyItemWidget(id_str='1_2') self.tree_widget.setItemWidget(tree_widget_item1, 0, child_widget1) self.tree_widget.setItemWidget(tree_widget_item1_1, 0, child_widget2) self.tree_widget.setItemWidget(tree_widget_item1_2, 0, child_widget3)
Example 5. Get the item currently selected
When item selected, call the function _display_selected()
self.tree_widget.itemPressed.connect(self._display_selected)
In the _display_selected(), get the selected items and display the names of them.
def _display_selected(self): selected_items = self.tree_widget.selectedItems() print("selected items are ", [item.text(0) for item in selected_items])
If you’d like to allow multiple selection, set selection mode to the tree widget. See “SelectionMode” in PySide documentation for details about SelectionMode.
* You can use QAbstractItemView.SelectionMode from PySide2.QtWidgets in PySide2.
self.tree_widget.setSelectionMode(QAbstractItemView.MultiSelection)
Example 6. access all items with iterator
You can access item with iterator.
def _iterate_all_items(self): it = QTreeWidgetItemIterator(self.tree_widget) while it.value(): item = it.value() print(item.text(0)) it.__next__()
Frequency used functions
To add header list
tree_widget.setHeaderLabels(["header_col1", "header_col2", ...])
To add top level item
tree_widget.addTopLevelItem(tree_widget_item)
To add child item to parent item
parent_tree_widget_item.addChild(child_tree_widget_item))
To get the list of children
tree_widget.children()
get and change the content of item
from PySide2.QtCore import Qt item = self.tree_widget.findItems("item1", Qt.MatchExactly, column=0)[0] item.setText(0, "changed_text")
To get items currently selected
self.tree_widget.selectedItems()
To hide header
self.tree_widget.setHeaderHidden(True)
Points
1. The argument of QTreeWidget should be the list of strings. If you pass single string as a string list, each character becomes the element of string list as below.
2. You can’t set child items to the same level at once. Even if you pass the list of strings as an argument of addChild(), the list item becomes one child item as below.
3. The number of items to display is defined by the number of header list. The number of items should be same as the the number of header labels or more.
4. If you use QWidget() as an item by using setItemWidget function, check the list of settings below.
Set PySide.QtGui.QWidget.autoFillBackground() property true, otherwise the widget’s background will be transparent, showing both the model data and the tree widget item.
Postscript
What is QTreeView?
QTreeView is one of the views used for model/view framework.
There are 2 types of model, QStandardItemModel (general dataset) and QFileSystemModel(path and directory structure), and QtreeView can display model as a tree.