Search code examples
pythonpyside2qtreewidgetqtreewidgetitemqcheckbox

How to get QTreeWidget item's text, when a checkbox within is toggled?


I've made a QTreeWidget that has a number of rows, each row with a text item, and a checkbox. How do I get the text, when the checkbox is toggled? I know that I can use currentItem() to get the currently selected TreeWidgetItem, but the row isn't necessarily selected. And I can't use the QTreeWidget's itemClicked/itemPressed signals, as they don't seem to emit when a checkbox widget within it is clicked.

from PySide2 import QtWidgets

class TestUI(QtWidgets.QDialog):
    def __init__(self):
        super(TestUI, self).__init__()
        self.tree = QtWidgets.QTreeWidget()
        self.tree.setHeaderLabels(('text', 'checkbox'))
        for x in range(0, 3):
            item = QtWidgets.QTreeWidgetItem(self.tree)
            item.setText(0, str(x))
            checkbox = QtWidgets.QCheckBox(parent=self.tree)
            checkbox.stateChanged.connect(self.checkbox_toggled)
            self.tree.setItemWidget(item, 1, checkbox)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.layout.addWidget(self.tree)
    
    def checkbox_toggled(self):
        print 'The text of the checkbox TreeWidgetItem is...'
        print None

if __name__ == "__main__":
    try:
        ui.deleteLater()
    except:
        pass
    ui = TestUI()
    ui.show()

Solution

  • The solution involves obtaining the QTreeWidgetItem to which the QCheckBox belongs, so a possible solution is to use the position of the pressed QCheckbox since it is a child of the viewport so the item can be obtained using the indexAt() method. To get the QCheckbox in the slot you can use the sender() method:

    class TestUI(QtWidgets.QDialog):
        def __init__(self):
            super(TestUI, self).__init__()
            self.tree = QtWidgets.QTreeWidget()
            self.tree.setHeaderLabels(("text", "checkbox"))
            for x in range(0, 3):
                item = QtWidgets.QTreeWidgetItem(self.tree)
                item.setText(0, str(x))
                checkbox = QtWidgets.QCheckBox()
                checkbox.stateChanged.connect(self.checkbox_toggled)
                self.tree.setItemWidget(item, 1, checkbox)
            self.layout = QtWidgets.QVBoxLayout(self)
            self.layout.addWidget(self.tree)
    
        def checkbox_toggled(self):
            checkbox = self.sender()
            print("sender: {}".format(checkbox))
            if checkbox is None:
                return
            item = self.tree.itemAt(checkbox.pos())
            if item is not None:
                print("The text of the checkbox TreeWidgetItem is {}".format(item.text(0)))