pythonpyqtpyqt5qradiobutton

Why does this code in PyQt allow me to leave all radio buttons unchecked?


I wrote a mini code using PyQt and I got surprised when I noticed that it allows me to leave all buttons on the left unchecked. I don't want this behaviour: one of them should always be selected. The right side of the window works, though. I don't really know why. Here's the code:

from PyQt5 import QtWidgets, QtGui, QtCore

class Win(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Win, self).__init__(parent)
        top_layout = QtWidgets.QHBoxLayout()

        top_layout_1 = QtWidgets.QHBoxLayout()
        self.thresh_btns = [QtWidgets.QRadioButton('L1'),
                            QtWidgets.QRadioButton('L2'),
                            QtWidgets.QRadioButton('L3')]
        self.thresh_btns[0].setChecked(True)
        for btn in self.thresh_btns:
            top_layout_1.addWidget(btn)

        timestamp_groupbox = QtWidgets.QGroupBox('Timestamp')
        top_layout_2 = QtWidgets.QVBoxLayout()
        self.timestamp_current = QtWidgets.QRadioButton('Current')
        self.timestamp_current.setChecked(True)
        self.timestamp_target = QtWidgets.QRadioButton('Last')
        top_layout_2.addWidget(self.timestamp_current)
        top_layout_2.addWidget(self.timestamp_target)
        timestamp_groupbox.setLayout(top_layout_2)

        top_layout.addLayout(top_layout_1)
        top_layout.addWidget(timestamp_groupbox)
        self.setLayout(top_layout)

if __name__ == '__main__':
   app = QtWidgets.QApplication([])
   ex = Win()
   ex.show()
   app.exec_()

Solution

  • If you want this behavior you have to use a QButtonGroup:

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class Win(QtWidgets.QDialog):
        def __init__(self, parent=None):
            super(Win, self).__init__(parent)
            top_layout = QtWidgets.QHBoxLayout()
    
            top_layout_1 = QtWidgets.QHBoxLayout()
            self.thresh_btns = [QtWidgets.QRadioButton('L1'),
                                QtWidgets.QRadioButton('L2'),
                                QtWidgets.QRadioButton('L3')]
            group_button = QtWidgets.QButtonGroup(self) # <---
            self.thresh_btns[0].setChecked(True)
            for btn in self.thresh_btns:
                top_layout_1.addWidget(btn)
                group_button.addButton(btn)             # <---
    
            timestamp_groupbox = QtWidgets.QGroupBox('Timestamp')
            top_layout_2 = QtWidgets.QVBoxLayout()
            self.timestamp_current = QtWidgets.QRadioButton('Current')
            self.timestamp_current.setChecked(True)
            self.timestamp_target = QtWidgets.QRadioButton('Last')
            top_layout_2.addWidget(self.timestamp_current)
            top_layout_2.addWidget(self.timestamp_target)
            timestamp_groupbox.setLayout(top_layout_2)
    
            top_layout.addLayout(top_layout_1)
            top_layout.addWidget(timestamp_groupbox)
            self.setLayout(top_layout)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        ex = Win()
        ex.show()
        sys.exit(app.exec_())