1
\$\begingroup\$

Firstly, have a good day to all, I've been trying to learn PyQt5 nowadays. I wrote a code about check box state changing depends on other check box. It looks work. I wonder your feed back. Thank you for your time.

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys


class CheckBox(QWidget):

    def __init__(self):
        super(CheckBox, self).__init__()
        self.features()
        self.checkbox()

    def features(self):
        self.setWindowTitle("Check Box")
        self.setGeometry(500, 200, 200, 200)

        self.show()

    def checkbox(self):
        # Check Box
        self.check_box1 = QCheckBox("Alive")
        self.check_box2 = QCheckBox("Dead")
        self.check_box3 = QCheckBox("No Idea")
        # Check Box State
        self.check_box3.setChecked(True)
        self.check_box1.stateChanged.connect(self.onStateChange)
        self.check_box2.stateChanged.connect(self.onStateChange)
        self.check_box2.stateChanged.connect(self.onStateChange)
        # Button
        self.push_button1 = QPushButton("Send")
        self.push_button1.clicked.connect(lambda: self.sendmessage(self.check_box1.isChecked(),
                                                                self.check_box2.isChecked(),
                                                           self.check_box3.isChecked(), self.label1))
        # Label
        self.label1 = QLabel("")
        # Vertical Lay Out
        v_box1 = QVBoxLayout()
        v_box1.addWidget(self.check_box1)
        v_box1.addWidget(self.check_box2)
        v_box1.addWidget(self.check_box3)
        v_box1.addWidget(self.push_button1)
        v_box1.addWidget(self.label1)
        # Horizontal Lay Out
        h_box1 = QHBoxLayout()
        h_box1.addStretch()
        h_box1.addLayout(v_box1)
        h_box1.addStretch()
        # Set Lay Out
        self.setLayout(h_box1)

    def onStateChange(self, state):
        if state == Qt.Checked:
            if self.sender() == self.check_box1:
                self.check_box2.setChecked(False)
                self.check_box3.setChecked(False)
            elif self.sender() == self.check_box2:
                self.check_box1.setChecked(False)
                self.check_box3.setChecked(False)
            elif self.sender() == self.check_box3:
                self.check_box1.setChecked(False)
                self.check_box2.setChecked(False)

    def sendmessage(self, cbox1, cbox2, cbox3, lab):
        if cbox1:
            lab.setText("Check Box 1")
        elif cbox2:
            lab.setText("Check Box 2")
        elif cbox3:
            lab.setText("Check Box 3")
        else:
            lab.setText("No Selection")


app = QApplication(sys.argv)
checkbox = CheckBox()
sys.exit(app.exec_())
\$\endgroup\$
3
\$\begingroup\$

I think there is a mistake, this line is defined twice (line 28):

self.check_box2.stateChanged.connect(self.onStateChange)

Therefore the event onStateChange is triggered twice when you check check_box2, which is logical.

I think you did a copy paste and the last should be check_box3. But your naming conventions are not intuitive, give your objects some more meaningful names, otherwise how are you going to tell the difference from your code.

If what you want is mutually exclusive checkboxes the implementation could be more straightforward. Personally I prefer to use radio buttons like in plain HTML because this is more intuitive (it is immediately obvious that only one answer is allowed).

First approach: a generic method that loops on the checkboxes in your form and unchecks all of them except the sender. Then you can simplify code and get rid of if/elif

Second approach: use QT built-in features. You could wrap your checkboxes in a QButtonGroup container.

A rectangular box before the text label appears when a QCheckBox object is added to the parent window. Just as QRadioButton, it is also a selectable button. Its common use is in a scenario when the user is asked to choose one or more of the available options.

Unlike Radio buttons, check boxes are not mutually exclusive by default. In order to restrict the choice to one of the available items, the check boxes must be added to QButtonGroup.

and:

As mentioned earlier, checkBox buttons can be made mutually exclusive by adding them in the QButtonGroup object.

self.bg = QButtonGroup()
self.bg.addButton(self.b1,1)
self.bg.addButton(self.b2,2)

QButtonGroup object, provides abstract container for buttons and doesn’t have a visual representation. It emits buttonCliked() signal and sends Button object’s reference to the slot function btngroup().

Source: PyQt - QCheckBox Widget

\$\endgroup\$
1
  • \$\begingroup\$ Thank you for your feedback. It mean a lot for me. I will definetly not ignore your feedback \$\endgroup\$ – Gokberk May 11 '20 at 9:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.