简体   繁体   中英

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_()

Try it:

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


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

        self._dictRB = {                                                   # +++                                         
            'rb1': False,
            'rb2': False,
            'rb3': False,
        }


        # Radio buttons
        self.group = QButtonGroup()

        self.b1 = QRadioButton('rb1')                                       # + 'rb1'  
        self.group.addButton(self.b1)
#        self.b1.clicked.connect(lambda: self.radioButtonClicked())

        self.b2 = QRadioButton('rb2')                                       # + 'rb2'  
        self.group.addButton(self.b2)
#        self.b2.clicked.connect(lambda: self.radioButtonClicked())

        self.b3 = QRadioButton('rb3')                                       # +++
        self.group.addButton(self.b3)

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

        self.group.buttonClicked.connect(self.check_button)                 # +++

    def check_button(self, radioButton):                                    # +++
        if self._dictRB[radioButton.text()]:
            self._dictRB[radioButton.text()] = False
            self._dictRB['rb3'] = True
            self.b3.setChecked(True)           
        else:
            for b in self._dictRB:
                self._dictRB[b] = False
            self._dictRB[radioButton.text()] = True
        print("clickеd button -> `{} - {}`".format(radioButton.text(), radioButton.isChecked()))        

    '''
    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_()

在此处输入图像描述

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_()

def delectRadioButtons(self):

    if self.radioButton_female.isCheckable() or self.radioButton_male.isCheckable():
        self.radioButton_male.setChecked(True)
        self.radioButton_female.setChecked(True)
        self.radioButton_male.setCheckable(False)
        self.radioButton_female.setCheckable(False)



    self.radioButton_female.setCheckable(True)
    self.radioButton_male.setCheckable(True)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM