ilstam
ilstam

Reputation: 1594

uncheck radiobutton - PyQt4

In this sample of code:

from PyQt4.QtGui import QDialog, QPushButton, QRadioButton, QHBoxLayout, QApplication, QButtonGroup
import sys

class Form(QDialog):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent=None)

        button = QPushButton('Button')
        self.radiobutton1 = QRadioButton('1')
        self.radiobutton2 = QRadioButton('2')
        #self.group = QButtonGroup()
        #self.group.addButton(self.radiobutton1)
        #self.group.addButton(self.radiobutton2)       
        #self.group.setExclusive(False)

        layout = QHBoxLayout()
        layout.addWidget(button)
        layout.addWidget(self.radiobutton1)
        layout.addWidget(self.radiobutton2)
        self.setLayout(layout)

        button.clicked.connect(self.my_method)

    def my_method(self):
        self.radiobutton1.setChecked(False)
        self.radiobutton2.setChecked(False)

app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()

When the button clicked I expect the selected radioButton to be unchecked, but that never happens. If I uncomment the comment lines and run the code, then I can uncheck radioButtons. But another problem occurs. Because the group is not exclusive, I can set both radioButtons checked something that must not happens.

What should I do to be able to unckeck the buttons while only one button at a time can be selected?

Upvotes: 3

Views: 11760

Answers (2)

BenAndo
BenAndo

Reputation: 11

To anyone looking for a simple fix to this very annoying problem, connect each button to a slot that controls the CheckState of the other buttons.

Simply add the list of buttons you want to a QButtonGroup, get the list of buttons, check that the sender is not the same button, and uncheck others.

Assuming that you instantiate your buttons in a loop, you can easily implement this:

self.bg = QButtonGroup()
self.bg.setExclusive(False)

for button in list_of_buttons:
    self.bg.addButton(button)
    button.clicked.connect(self.uncheck_other_buttons)


def uncheck_other_btns(self):
    for button in self.bg.buttons():  # returns the list of all added buttons
        if self.sender() != button:   # in PyQt5, button.objectName() fails if name isn't set, 
                                      # instead, simply check that the signal sender() object  
                                      # is not the same object as the clicked button
            button.setChecked(False)  # then set all other buttons to be unchecked

Upvotes: 1

unutbu
unutbu

Reputation: 879103

This feels like cheating, but it works:

import sys
import PyQt4.QtGui as QtGui

class Form(QtGui.QDialog):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)

        button = QtGui.QPushButton('Button')
        button.clicked.connect(self.my_method)

        self.radiobutton1 = QtGui.QRadioButton('1')
        self.radiobutton2 = QtGui.QRadioButton('2')

        layout = QtGui.QHBoxLayout()
        layout.addWidget(button)
        layout.addWidget(self.radiobutton1)
        layout.addWidget(self.radiobutton2)
        self.setLayout(layout)

        self.group = QtGui.QButtonGroup()
        self.group.addButton(self.radiobutton1)
        self.group.addButton(self.radiobutton2)       

    def my_method(self):
        self.group.setExclusive(False)        
        self.radiobutton1.setChecked(False)
        self.radiobutton2.setChecked(False)
        self.group.setExclusive(True)

app = QtGui.QApplication(sys.argv)
form = Form()
form.show()
app.exec_()

As you've pointed out, when self.group.setExclusive(False) is set, you can untoggle both radio buttons.

And when self.group.setExclusive(True), only one radio button can be set.

So my_method simply calls self.group.setExclusive(False) so it can unset both radio buttons, then resets self.group.setExclusive(True).


PS. I think parent should not be set to None on this line:

super(Form, self).__init__(parent = None)

since if a non-trivial parent is sent to Form, you would probably want to pass that parent on to QDialog.__init__.

Upvotes: 7

Related Questions