Search code examples
pythonpyside2

Parent a QTreeWidgetItem to an existing QTreeWidgetItem to second column maintaining the first column


I created a QTreeWidget and parented a QTreeWidgetItem using the QTreeWidget.addTopLevelItem method. The QTreeWidgetItem are parented to each other with QTreeWidgetItem.addChild. Which works great. However, I want to add a check box that is flushed left and not right next to each QTreeWidgetItem (which is easy by adding QtCore.Qt.ItemIsUserCheckable). I can add a check box to the second column and maintain the tree. By all that gets messed up when I add the checkbox to the first column and the setText to the secound column.

If I add a check box to a QTreeWidgetItem, I get something like:

[   ] red
    [   ] blue  
    [   ] green 
        [   ] orange 
            [    ] purple  
                 [   ] pink

I don't want the check boxes right next to the color. I am looking for:

Col1 | Col2
[   ] red 
[   ]     blue 
[   ]     green 
[   ]         orange 
[   ]            purple 
[   ]                pink

I know I need to add the widget in the QtWidgets.QTreeWidgetItem like:

self.button = QtWidgets.QPushButton("L") # testing with a button
treeWidget = self.treeWidget()
treeWidget.setItemWidget(self, 0,self.button)

What I am looking for in the tree. I am looking to make the tree like the following image. Nevermind the 3 columns, I am using 2


Solution

  • You could set the check boxes to the second column in your QTreeWidget and swap the first and second sections of the header, e.g.

    from PySide2 import QtWidgets, QtCore
    
    class MyItem(QtWidgets.QTreeWidgetItem):
        def __init__(self, label):
            super().__init__([label, ''])
            self.setCheckState(1, QtCore.Qt.Unchecked)
            self.setFlags(self.flags() | QtCore.Qt.ItemIsAutoTristate)
    
    class MyTree(QtWidgets.QTreeWidget):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.setColumnCount(2)
            self.header().swapSections(1,0)
            self.header().resizeSection(1, 80)
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication([])
        tree = MyTree()
        tree.setHeaderLabels(['label', 'checked'])
        items = [MyItem(f'item {i}') for i in range(6)]
        tree.insertTopLevelItems(0, items)
        for i, item in enumerate(items):
            for j in range(4):
                items[i].addChild(MyItem(f'item {i}-{j}'))
        tree.show()
        app.exec_()
    

    Note that I've also set QtCore.Qt.ItemIsAutoTristate to automatically update the checked state of the parent/children of an item when its checked state changes. screenshot of tree with checkboxes on the left