QT, al contrario de otras librerias centradas en el desarrollo de interfaces gráficas de usuario, no implementa un widget que permita agrupar una lista de radio buttons. Crear un nuevo Widget que permita esto, no es muy complicado. A continuación el código:

Agrupar una lista de radio buttons


from PyQt4.QtGui import *
from PyQt4.QtCore import *


class QRadioButtonGroupBox(QGroupBox):

    selectItemChanged = pyqtSignal(int)

    def __buttonGroupClickedSlot(self, index):
        self.selectItemChanged.emit(index)

    def __init__(self, *args):
        QGroupBox.__init__(self, *args)
        self.box = QFormLayout(parent=self)
        self.buttonGroup = QButtonGroup()
        QObject.connect(self.buttonGroup, SIGNAL("buttonClicked(int)"), 
                        self.__buttonGroupClickedSlot)

    def selectedItem(self):
        return self.buttonGroup.checkedId()

    def setChecked_(self, index, isChecked=True):
        self.buttonGroup.button(index).setChecked(isChecked)

    def addItem(self, text, isChecked=False):
        radioButton = QRadioButton(text)
        index = len(self.buttonGroup.buttons())
        self.buttonGroup.addButton(radioButton, index)
        self.buttonGroup.button(index).setChecked(isChecked)
        self.box.addRow(radioButton)
        return index

    def addItems(self, *items):
        for item in items:
            self.addItem(item)

    def removeItems(self):
        for button in self.buttonGroup.buttons():
            self.buttonGroup.removeButton(button)
            self.box.removeWidget(button)

selectedItem retorna el número de radiobutton seleccionada, setChecked_ permite seleccionar uno de los radiobuttons de la lista, addItem y addItems sirve para añadir radiobuttons y removeItems para eliminar la lista completa de radiobutton. También incluye el signal selectItemChanged que se dispara cuando el usuario selecciona un radiosbutton de la lista.

A continuación una demo:

def selectedItemChangedSlot(index):
    print 'ha seleccionado:', index

app = QApplication(sys.argv)
main = QRadioButtonGroupBox('Mi color favorito')
main.selectItemChanged.connect(selectedItemChangedSlot)

main.addItem('1')
main.addItem('2')
main.addItem('3')
main.removeItems()

main.addItem('Rojo')
main.addItem('Azul', isChecked=True)
main.addItem('Amarillo')
main.addItems('Marron', 'Naranja', 'Verde')

main.show()
sys.exit(app.exec_())

Resultado:

agrupar una lista de radio buttons

Punto Extra

A veces puede ser interesante tener la posibilidad de acompañar al radio button de un widget extra. El siguiente código permite esto:

from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys


class QRadioButtonGroupBox(QGroupBox):

    selectItemChanged = pyqtSignal(int, QWidget)

    def __setEnabledWidget(self, index):
        widget = None
        for button in self.buttonGroup.buttons():
            if button.buddie:
                if index == self.buttonGroup.id(button):
                    button.buddie.setEnabled(True)
                    widget = button.buddie
                else:
                    button.buddie.setEnabled(False)
        return widget

    def __buttonGroupClickedSlot(self, index):
        widget = self.__setEnabledWidget(index)
        self.selectItemChanged.emit(index, widget)

    def __init__(self, *args):
        QGroupBox.__init__(self, *args)
        self.box = QFormLayout(parent=self)
        self.buttonGroup = QButtonGroup()
        QObject.connect(self.buttonGroup, SIGNAL("buttonClicked(int)"),
                        self.__buttonGroupClickedSlot)

    def selectedItem(self):
        return self.buttonGroup.checkedId()

    def buddie(self, index):
        button = self.buttonGroup.button(index)
        return button.buddie

    def setChecked_(self, index):
        self.__setEnabledWidget(index)
        self.buttonGroup.button(index).setChecked(True)

    def addItem(self, text, widget=None, isChecked=False):
        radioButton = QRadioButton(text)
        index = len(self.buttonGroup.buttons())
        self.buttonGroup.addButton(radioButton, index)
        self.buttonGroup.button(index).setChecked(isChecked)
        radioButton.buddie = widget
        if widget:
            self.box.addRow(radioButton, widget)
            widget.setEnabled(isChecked)
        else:
            self.box.addRow(radioButton)
        return index

    def addItems(self, *items):
        for item in items:
            self.addItem(item)

    def removeItems(self):
        for button in self.buttonGroup.buttons():
            self.buttonGroup.removeButton(button)
            if button.buddie:
                self.box.removeWidget(button.buddie)
                button.buddie = None
            self.box.removeWidget(button)

Una demo:

def selectedItemChangedSlot(index, widget):
    print 'ha seleccionado:', index
    print 'widget asociado:', widget

app = QApplication(sys.argv)
main = QRadioButtonGroupBox('Mi color favorito')
main.selectItemChanged.connect(selectedItemChangedSlot)
main.addItem('Rojo')
main.addItem('Azul', isChecked=True)
main.addItem('Amarillo')
main.addItems('Marron', 'Naranja', 'Verde')
colores = QComboBox()
colores.addItems(['violeta', 'fucsia', 'lima'])
main.addItem('otro color', widget=colores)
main.addItem('mas colores:', QLineEdit())
main.show()
sys.exit(app.exec_())

Resultado:

agrupar una lista de radio buttons