Search code examples
pythonpyqtqradiobutton

Toggling a QRadioButton in pyqt5: uncheck when a checked radio button is clicked


I'm using some QRadioButtons inside a QButtonGroup in pyQt5. I would like the user to be able to select one of the exclusive options or none, so if he accidentally clicks a radio button, he should be able to click it again to uncheck it.

My current approach is to connect the clicked method to a custom function that checks the button status, but I couldn't figure how to do it in a simple way, without using shady click counters.

from PyQt5.QtWidgets import QApplication, QWidget, QRadioButton, QHBoxLayout, QButtonGroup
import sys


class MainWindow(QWidget):

    def __init__(self):

        super().__init__()

        # Radio buttons
        self.group = QButtonGroup()

        self.b1 = QRadioButton()
        self.group.addButton(self.b1)
        self.b1.clicked.connect(lambda: self.radioButtonClicked())

        self.b2 = QRadioButton()
        self.group.addButton(self.b2)
        self.b2.clicked.connect(lambda: self.radioButtonClicked())

        # Layout
        self.layout = QHBoxLayout()
        self.layout.addWidget(self.b1)
        self.layout.addWidget(self.b2)
        self.setLayout(self.layout)


    def radioButtonClicked(self):
        if self.sender().isChecked():
            self.sender().setAutoExclusive(False)
            self.sender().setChecked(False) # This is not working, as it fires on the first click
            self.sender().setAutoExclusive(True)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec_()

Solution

  • Finally, I've come with a solution in two steps: first, make the button group not exclusive, so buttons can be unchecked when clicked again. And second, when a radio is selected, uncheck every other button.

    from PyQt5.QtWidgets import (QApplication, QWidget, QRadioButton,QHBoxLayout, QButtonGroup)
    import sys
    
    class MainWindow(QWidget):
    
        def __init__(self):
    
            super().__init__()
    
            # Radio buttons
            self.group = QButtonGroup()
            self.group.setExclusive(False)  # Radio buttons are not exclusive
            self.group.buttonClicked.connect(self.check_buttons)
    
            self.b1 = QRadioButton()
            self.group.addButton(self.b1)
    
            self.b2 = QRadioButton()
            self.group.addButton(self.b2)
    
            # Layout
            self.layout = QHBoxLayout()
            self.layout.addWidget(self.b1)
            self.layout.addWidget(self.b2)
            self.setLayout(self.layout)
    
    
        def check_buttons(self, radioButton):
            # Uncheck every other button in this group
            for button in self.group.buttons():
                if button is not radioButton:
                    button.setChecked(False)
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        window = MainWindow()
        window.show()
        app.exec_()