0

I am working on a (fairly basic) feature in a PySide2 application. The application contains a list of checkboxes, and when a checkbox is checked, I need to append the index of the checkbox to a list. My unsuccessful attempt at this can be seen below...

checked = []

cb1 = QCheckBox('1')
cb2 = QCheckBox('2')
cb3 = QCheckBox('3')

cbs = [cb1, cb2, cb3]

for n, cb in enumerate(cbs):
    cb.stateChanged.connect(lambda: checked.append(n) if cb.isChecked() else checked.remove(n))

I have found that the issue here is with "late binding" as described in python's common gotchas. The value of n is always 2 whenever the checkbox is activated. However, I have tried using the following solutions from the docs which also have failed.

for n, cb in enumerate(cbs):
    cb.stateChanged.connect(lambda n=n: checked.append(n) if cb.isChecked() else checked.remove(n))
for n, cb in enumerate(cbs):
    cb.stateChanged.connect(lambda n=n, button=button: checked.append(n) if cb.isChecked() else checked.remove(n))

The first solution gives seemingly random and incorrect values for n, and the second somehow turns the button variable into an integer. In a case with only a few checkboxes I would consider setting these functions one-by-one but in the actual application there needs to be around 20 checkboxes. Any insight on this would be greatly appreciated!

Michael Hoefler
  • 105
  • 2
  • 9

1 Answers1

1

Try it:

class Demo(QWidget):
    def __init__(self):
        super().__init__()

        self._checked = []

        self.cb1 = QCheckBox('1')
        self.cb2 = QCheckBox('2')
        self.cb3 = QCheckBox('3')
        
        layout = QVBoxLayout(self)
        layout.addWidget(self.cb1)
        layout.addWidget(self.cb2)
        layout.addWidget(self.cb3)

        cbs = [self.cb1, self.cb2, self.cb3]
        for n, cb in enumerate(cbs):
            cb.stateChanged.connect(lambda state, n=n+1: self.list_checked(state, n))
            
    def list_checked(self, state, n):
        if state:
            self._checked.append(n)
        else:
            self._checked.remove(n)
        print(self._checked)

   
if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    wform = Demo()
    wform.resize(200, 100)
    wform.show()
    sys.exit(app.exec_())  

enter image description here

S. Nick
  • 12,879
  • 8
  • 25
  • 33