1

I've made a QTreeWidget where I have comboBox as a QTreeWidgetItem. How do I hook up the signal correctly so that each comboxBox index changed will change the same row in the treeWidget ?

exampleWindow

Say if I change the action in row itemB from Add to Remove. It will change itemB backgroundColor to somethingelse...

data = { 'GroupA': [
                  {'itemA': {'action' : 'Add'}},
                  {'itemB':{'action' : 'Updates'}},
                  ],
        'GroupB': [
                  {'someOtherItemA': {'action' : 'Updates'}},
                  {'someOtherItemA':{'action' : 'Add'}},
                  ]

        }


class Window(QtGui.QMainWindow):

    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        self.treeWidget=QtGui.QTreeWidget(self)
        self.treeWidget.setGeometry(QtCore.QRect(50,20,450,240))

        self.header=QtGui.QTreeWidgetItem(["Item","Action"])
        self.treeWidget.setHeaderItem(self.header)

        for group in data:
            groupItem=QtGui.QTreeWidgetItem(self.treeWidget)
            groupItem.setText(0,group)
            groupItem.setFlags( QtCore.Qt.ItemIsEnabled )

            for itemDict in data[group]:
                for item in itemDict:

                    itemWidget=QtGui.QTreeWidgetItem(groupItem, [item])
                    itemWidget.setText(0, item)

                    action = itemDict[item]['action']
                    self.action = self._actionCombo()
                    self.treeWidget.setItemWidget(itemWidget, 1, self.actionCombo)
                    slotLambda = lambda: self.actionChanged(itemWidget)
                    self.action.currentIndexChanged.connect(slotLambda)

        self.treeWidget.expandAll()


    @QtCore.pyqtSlot(QtGui.QTreeWidgetItem)
    def actionChanged(self, treeWidgetItem):
        treeWidgetItem.setBackgroundColor(0, QtGui.QColor(0,0,0))

    def _actionCombo(self):

        self.actionCombo = QtGui.QComboBox()
        actionLists = ['Add', 'Updates', 'Keep', 'Remove']
        for actionItem in actionLists:
            self.actionCombo.addItem(actionItem)

        return self.actionCombo

    def report(self):
        #construct the data back in a dictionary

        newData = {}
        return newData

The other question is how do I construct a dictionary based on the QtreeWidget data? So that I will get what the user chosen for the action on each item and report back as a dictionary like following?

dataReportBack = { 'GroupA': [
                      {'itemA': {'action' : 'Add'}},
                      {'itemB':{'action' : 'Updates'}},
                      ],
            'GroupB': [
                      {'someOtherItemA': {'action' : 'Updates'}},
                      {'someOtherItemA':{'action' : 'Add'}},
                      ]

            }
Brendan Abel
  • 35,343
  • 14
  • 88
  • 118
moDong
  • 223
  • 2
  • 5
  • 9

1 Answers1

2

It's not really clear how you're creating each combobox (are self.action and self.actionCombo being set to a new combobox each time?).

Assuming you're just creating a new QComboBox for each item widget, the simplest way would be to just pass both the combobox and the itemwidget to the signal handler.

class Widget(...)
    ...

    def func(self):        
        ...
        for item in itemDict:
            itemWidget = QtGui.QTreeWidgetItem(groupItem, [item])
            itemWidget.setText(0, item)
            # I'm guessing this creates a new QComboBox
            actionCombo = self._actionCombo()
            self.treeWidget.setItemWidget(itemWidget, 1, actionCombo)
            actionCombo.currentIndexChanged.connect(lambda: self.on_actionComboChanged(actionCombo, itemWidget)

    def on_actionComboChanged(self, actionCombo, itemWidget)
        if actionCombo.currentText() == 'Add':
            color = QtGui.QColor(QtCore.Qt.green)
        else:
            color = QtGui.QColor(QtCore.Qt.red)
        itemWidget.setData(QtCore.Qt.BackgroundRole, QtGui.QBrush(color))
Brendan Abel
  • 35,343
  • 14
  • 88
  • 118