Pyqt5 QTreeWIdgetItem with select one item checkbox at atime

417 views Asked by At

I have a QTreeWidget and each QTreeWidgetItem has 3 checkboxes.I would like to do two things but I can't figure how to do them.

  1. The user should be able to select only one check box at time for each QTreeWidgetItem.So the selection of a given checkbox of a QTreeWidgetItem should deselect the other checkboxes of that QTreeWidgetItem.
  2. The selection/deselection of a given parent QTreeWidgetItem checkbox should select/deselect all its child checkboxes in the same column. Below is my code:

Any help would be highly appreciated

from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5.Qt import Qt
import sys

def main():
    app     = QtWidgets.QApplication(sys.argv)
    tree    = QtWidgets.QTreeWidget()
    tree.resize(500, 200)
    headerItem  = QtWidgets.QTreeWidgetItem()
    item    = QtWidgets.QTreeWidgetItem()
    tree .setColumnCount(4)
    tree .setHeaderLabels(["pluto", "X", "Y", "Z", ""])
    for i in range(3):
        parent = QtWidgets.QTreeWidgetItem(tree)
        parent.setText(0, "Parent {}".format(i))
        parent.setCheckState(1, Qt.Unchecked)
        parent.setCheckState(2, Qt.Unchecked)
        parent.setCheckState(3, Qt.Unchecked)
        #parent.setFlags(parent.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
        for x in range(5):
            child = QtWidgets.QTreeWidgetItem(parent)
            child.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
            child.setText(0, "Child {}".format(x))
            child.setCheckState(1, Qt.Unchecked)
            child.setCheckState(2, Qt.Unchecked)
            child.setCheckState(3, Qt.Unchecked)


    tree.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()
1

There are 1 answers

0
alvy On

I have solved my own problem by using itemClicked.Here is my solution incase someone is interested.

from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5.Qt import Qt
import sys

class treeManagement:
    def __init__(self):
        app     = QtWidgets.QApplication(sys.argv)
        self.tree    = QtWidgets.QTreeWidget()
        self.tree.resize(500, 200)
        headerItem  = QtWidgets.QTreeWidgetItem()
        item    = QtWidgets.QTreeWidgetItem()
        self.tree .setColumnCount(4)
        self.tree .setHeaderLabels(["pluto", "X", "Y", "Z", ""])
        for i in range(3):
            parent = QtWidgets.QTreeWidgetItem(self.tree)
            parent.setText(0, "Parent {}".format(i))
            parent.setCheckState(1, Qt.Unchecked)
            parent.setCheckState(2, Qt.Unchecked)
            parent.setCheckState(3, Qt.Unchecked)

            for x in range(5):
                child = QtWidgets.QTreeWidgetItem(parent)
                child.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
                child.setText(0, "Child {}".format(x))
                child.setCheckState(1, Qt.Unchecked)
                child.setCheckState(2, Qt.Unchecked)
                child.setCheckState(3, Qt.Unchecked)

        self.tree.itemClicked.connect(self.checkboxSelectionChanged)
        self.tree.show()
        sys.exit(app.exec_())

    def checkboxSelectionChanged(self,selectedItem, selectedColumn):
        print(selectedItem.text(0))
        print(selectedColumn)
        # In this method I manage checkbox selected

        if selectedItem is None:
            return

        # 0-The item is unchecked.
        # 1-The item is partially checked. Items in hierarchical models may be partially checked if some, but not all,
        # of their children are checked.
        # 2-The item is checked.

        sumCheckState = selectedItem.checkState(1) + selectedItem.checkState(2) + selectedItem.checkState(3)

        state = QtCore.Qt.Unchecked
        for i in range(1, 4):
            if selectedColumn != i:
                if sumCheckState >= 4:  # Prevent update if user clicked in the space near checkbox or there's only one
                    # checkbox currently checked in this row
                    selectedItem.setCheckState(i, QtCore.Qt.Unchecked)
            elif selectedItem.childCount() > 0:  # selectedColumn=i
                for j in range(selectedItem.childCount()):
                    child = selectedItem.child(j)
                    for k in range(1, 4):
                        if selectedColumn != k:
                            if sumCheckState >= 4 or (sumCheckState == 2 and child.checkState(k) == QtCore.Qt.Checked
                                and selectedItem.checkState(selectedColumn) != QtCore.Qt.Unchecked):
                                # Prevent update if user clicked in the space near checkbox or there's only one
                                # checkbox currently checked in this row
                                child.setCheckState(k, QtCore.Qt.Unchecked)
                        else:
                            child.setCheckState(k, selectedItem.checkState(selectedColumn))
            elif selectedItem.parent() is not None:
                # I have clicked on a child element so no parent should be in checked state
                if sumCheckState >= 4:  # Prevent update if user clicked in the space near checkbox or there's only one
                    # checkbox currently checked in this row
                    for i in range(1, 4):
                        selectedItem.parent().setCheckState(i, QtCore.Qt.Unchecked)

if __name__ == '__main__':
    t=treeManagement()