pythonpyqtpyqt5qgroupbox

Can I get a signal from a QGroupbox when one of the radiobuttons in it is changed?


I'm making a user-interface in PYQT 5. It includes a QGroupBox containing several QRadioButton. When there is a toggled event I check the buttons and do some stuff. The problem is that there are two toggled events because one button is toggled on and one off so my code is always running twice.

I have been looking for an event from the QGroupBox instead. That should only happen once instead of twice when i toggle a radiobutton.

    def __init__(self):
        self.radioButton1.toggled.connect(self.update_stimulus)
        self.radioButton2.toggled.connect(self.update_stimulus)
        self.radioButton3.toggled.connect(self.update_stimulus)

    def update_stimulus(self):
        if self.radioButton1.isChecked():
            print('1')
        if self.radioButton2.isChecked():
            print('2')
        if self.radioButton3.isChecked():
            print('3')
        # Do stuff based on button positions

I tried using

self.groupBox.toggled.connect(self.update_stimulus)

But that only works if the groupbox itself is toggled. Is there any way to get a signal from the groupbox when one of the radiobuttons changes or do I have to find some way of doing it with the indivdual signals from the radiobuttons?


Solution

  • As @ekhumoro explains, you can add the checked parameter to the function and do your processing only if it's True:

    def update_stimulus(self, checked):
        if not checked:
            return
        if self.radioButton1.isChecked():
            print('1')
        if self.radioButton2.isChecked():
            print('2')
        if self.radioButton3.isChecked():
            print('3')
    

    Keep in mind, though, that if you want to have different radio button "groups" within the same groupbox, none of this will work properly as they will all be considered as part of the same single group: all Qt buttons (widgets that inherit QAbstractButton: QPushButton, QToolButton, QCheckBox and QRadioButton) have an autoExclusive property which is off by default except from radio buttons. This property makes all button that belong to the same parent widget automatically exclusive.

    If you need different groups within the same parent, the solution is to use a QButtonGroup, which extends the exclusive functionality by limiting the membership of each button to a specific group.

    def __init__(self):
        # ...
        self.buttonGroupA = QtWidgets.QButtonGroup()
        self.buttonGroupA.addButton(self.radioButton1)
        self.buttonGroupA.addButton(self.radioButton2)
        self.buttonGroupA.addButton(self.radioButton3)
        self.buttonGroupA.buttonToggled[QtWidgets.QAbstractButton, bool].connect(self.update_stimulusA)
    
        self.buttonGroupB = QtWidgets.QButtonGroup()
        self.buttonGroupB.addButton(self.radioButton4)
        self.buttonGroupB.addButton(self.radioButton5)
        self.buttonGroupB.addButton(self.radioButton6)
        self.buttonGroupB.buttonToggled[QtWidgets.QAbstractButton, bool].connect(self.update_stimulusB)
    
    def update_stimulusA(self, btn, checked):
        if not checked:
            return
        # do something with group A
    
    def update_stimulusB(self, btn, checked):
        if not checked:
            return
        # do something with group B
    

    Creation of a button group is also possible from Designer: just select at least two buttons that will be members of the same group, right click on one of them, go to the "Assign to button group" sub menu and select "New button group". To add a button to an existing group, just use the same context menu and choose the group you want to add that button to.