1

I create some QCheckBoxes from a dict using the dict keys as checkbox text. Then I connect the signal to the update function using a lambda expression. What I want to pass to this update function is the text of the checkbox so each lambda has its specific argument. Nevertheless I always get the text of the last added widget, no matter which checkbox I click. Do I miss something crucial about the concept of signal passing using lambda?

import sys
from PyQt5.QtWidgets import QDialog, QCheckBox, QVBoxLayout, QApplication, QSlider, QLabel


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

        layout = QVBoxLayout()

        cb_dict = {"cb1": False, "cb2": True, "cb3": False}
        cb_widget_list = list()

        for checkbox in cb_dict:
            widget = QCheckBox(checkbox)
            widget.stateChanged.connect(lambda: self.update(checkbox))
            cb_widget_list.append(widget)

        for widget in cb_widget_list:
            layout.addWidget(widget)
        self.setLayout(layout)

    def update(self, origin: str):
        print("Checkbox {} has changed".format(origin))


if __name__ == '__main__':
    app = QApplication(sys.argv)

    main = Window()
    main.show()

    sys.exit(app.exec_())

So the output is always Checkbox cb3 has changed.

po.pe
  • 1,047
  • 1
  • 12
  • 27

1 Answers1

2

void QCheckBox::stateChanged(int state)

This signal is emitted whenever the checkbox's state changes, i.e., whenever the user checks or unchecks it.

state contains the checkbox's new Qt::CheckState.

Since you want to pass another parameter, you should do this:

        widget.stateChanged.connect(
            lambda state, checkbox=checkbox: self.update(state, checkbox)  # +++
        )

import sys
from PyQt5.QtWidgets import QDialog, QCheckBox, QVBoxLayout, QApplication, QSlider, QLabel


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

        layout = QVBoxLayout()

        cb_dict = {"cb1": False, "cb2": True, "cb3": False}
        cb_widget_list = list()

        for checkbox in cb_dict:
            widget = QCheckBox(checkbox)
            widget.stateChanged.connect(
                lambda state, checkbox=checkbox: self.update(state, checkbox)  # +++
            )
            cb_widget_list.append(widget)

        for widget in cb_widget_list:
            layout.addWidget(widget)
        self.setLayout(layout)

    def update(self, state, origin: str):                                      # + state
        print("Checkbox {} has changed: {}".format(origin, state))


if __name__ == '__main__':
    app = QApplication(sys.argv)

    main = Window()
    main.show()

    sys.exit(app.exec_())

enter image description here

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