Python PyQt - Checkbox to uncheck all other checkb

2019-07-07 18:17发布

问题:

I'm trying to put in some validation such that:

  • When either "Select A" or "Select B" is checked, "None Selected" is automatically unchecked
  • When "None Selected" is checked, both "Select A" and "Select B" are automatically unchecked

But when I run this code, clicking any checkbox will uncheck all the 3 checkboxes.

i.e. The window initializes with "None Selected" checked. But when I click "Select A", it unchecks "None Selected", which is intended, but "Select A" doesn't get checked.

What am I doing wrong?


import sys
import PyQt5

class Test(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        checkBoxNone = QCheckBox("None Selected")
        checkBoxA    = QCheckBox("Select A")
        checkBoxB    = QCheckBox("Select B")

        checkBoxNone.setChecked(True)
        checkBoxNone.stateChanged.connect(lambda checked: (checkBoxA.setChecked(False), checkBoxB.setChecked(False)))
        checkBoxA.stateChanged.connect(lambda checked: checkBoxNone.setChecked(False))
        checkBoxB.stateChanged.connect(lambda checked: checkBoxNone.setChecked(False))

        grid = QGridLayout()

        grid.addWidget(checkBoxNone, 1, 0)
        grid.addWidget(checkBoxA, 2, 0)
        grid.addWidget(checkBoxB, 3, 0)

        self.setLayout(grid)
        self.setWindowTitle('Test')
        self.show()

if __name__ == '__main__':
    if not QApplication.instance():
        app = QApplication(sys.argv)
    else:
        app = QApplication.instance()
    ex = Test()
    sys.exit(app.exec_())

回答1:

The problem is caused because according to your requirements, you should only make those options if some QCheckBox is checked but you do not do that verification, to be able to handle it properly, create a slot and to know which object the signal was emited, the sender() method:

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

class Test(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.checkBoxNone = QCheckBox("None Selected")
        self.checkBoxA    = QCheckBox("Select A")
        self.checkBoxB    = QCheckBox("Select B")

        self.checkBoxNone.setChecked(True)
        self.checkBoxNone.stateChanged.connect(self.onStateChange)
        self.checkBoxA.stateChanged.connect(self.onStateChange)
        self.checkBoxB.stateChanged.connect(self.onStateChange)

        grid = QGridLayout(self)

        grid.addWidget(self.checkBoxNone, 1, 0)
        grid.addWidget(self.checkBoxA, 2, 0)
        grid.addWidget(self.checkBoxB, 3, 0)
        self.setWindowTitle('Test')
        self.show()

    @pyqtSlot(int)
    def onStateChange(self, state):
        if state == Qt.Checked:
            if self.sender() == self.checkBoxNone:
                self.checkBoxA.setChecked(False)
                self.checkBoxB.setChecked(False)
            elif self.sender() in (self.checkBoxA, self.checkBoxB):
                self.checkBoxNone.setChecked(False)