Nominate our 2022 Qt Champions!

QRadioButton group and QDataWidgetMapper

  • I wanted to be able to represent an exclusive set of options as several radio buttons. I also wanted to be able to store an integer Id corresponding to which option was selected in my database, and ideally, use QDataWidgetMapper to do it. Yes, a combo box could serve here, but for this particular UI, I would prefer option buttons (in part because there are other widgets that become enabled/disabled as a result of the selected option, and they are laid out in a way that helps make the relationship apparent.)

    I came across QButtonGroup and thought that might solve my problem, but QButtonGroup is not a QWidget, which is needed by QDataWidgetMapper. I also came acroos QGroupBox which is a QWidget, but it doesn't have a property to get at the currently selected option (and why should it - a group box could have all sorts of different sets of child items.)

    I thought this would be a fairly common problem, so I wanted to present my solution so that:

    • Those of you who have tackled this problem before can chime in on the solution
    • Those of you who are looking for a solution have a starting place

    I wanted to use a widget as a starting place, and then add to the interface:

    • A method for assigning an integer Id to each option button
    • A property for getting/setting the current Id / selected option button

    The currently selected propery needs to be a property in order to work with QDataWidgetMapper. The best widget to use as a starting place seemed to be...well...QWidget!

    Here is my OptionGroup class:

    #ifndef OPTIONGROUP_H
    #define OPTIONGROUP_H

    #include <QWidget>
    #include <QMap>

    class QRadioButton;

    class OptionGroup : public QWidget
    Q_PROPERTY(int currentSelection READ currentSelection WRITE setCurrentSelection USER true)

    explicit OptionGroup(QWidget *parent = 0);

    int currentSelection() const;
    void setCurrentSelection(int selection);
    void setSelectionId(QRadioButton *button, int id);

    void selectionChanged(int selection);

    public slots:
    void buttonToggled(bool checked);

    int currentSelection_;
    QMap<int, QRadioButton*> buttonMap_;
    QMap<QRadioButton*, int> revButtonMap_;

    #endif // OPTIONGROUP_H

    @#include <QRadioButton>
    #include "optiongroup.h"

    OptionGroup::OptionGroup(QWidget *parent) :
    QWidget(parent), currentSelection_(-1)

    int OptionGroup::currentSelection() const
    { return currentSelection_; }

    void OptionGroup::setCurrentSelection(int selection)
    // If the specified selection id is not in our button map,
    // then it is invalid, set selection to -1. Otherwise,
    // update the selection to user specified value

    auto iter = buttonMap_.find(selection);
    if (iter == buttonMap_.end() || selection < 0) {
        currentSelection_ = -1;
        for (iter = buttonMap_.begin(); iter != buttonMap_.end(); ++iter)
    } else {
        currentSelection_ = selection;


    void OptionGroup::setSelectionId(QRadioButton* button, int id)
    // Make sure we got a valid Id (non-negative)
    // Also then listen for signals from this button
    if (id >= 0) {
    buttonMap_[id] = button;
    revButtonMap_[button] = id;
    connect(button, SIGNAL(toggled(bool)), this, SLOT(buttonToggled(bool)));

    void OptionGroup::buttonToggled(bool checked)
    if (checked == true) {
    QRadioButton* btn = qobject_cast<QRadioButton*>(sender());
    currentSelection_ = revButtonMap_[btn];
    emit selectionChanged(currentSelection_);

    Note that you'll need to call setSelectionId() to assign an Id to each QRadioButton. -1 is used to represent an invalid or unset Id, so be sure to pass something that is greater than or equal to 0.

    If you had:

    • ui->optBtnA which corresponds with Id 0
    • ui->optBtnB which corresponds with Id 1
    • ui->optBtnC which corresponds with Id 2

    And they were all children of an OptionGroup ui->optionGroup, you would do this:
    ui->optionGroup.setSelectionId(ui->optBtnA, 0);
    ui->optionGroup.setSelectionId(ui->optBtnB, 1);
    ui->optionGroup.setSelectionId(ui->optBtnC, 2);

    // QDataWidgetMapper mapper;
    // int optionField; This is which field in your data model you are storing the option value in
    mapper.addMapping(ui->optionGroup, optionField);

    This seems to be working well enough. Having the two maps for looking up Ids/QRadioButton* is redundant. Since the list of options is always likely to be pretty small, so I might use a QList of QPair's and just sequentially search them.

    Hit me with your critiques, and hope this helps somebody else out.

  • Looks really useful for the right situation... thanks for taking the trouble to post it :-)

  • Code translated in Pyside :

    from PySide.QtCore import *
    from PySide.QtGui import *

    class optionGroup(QWidget):

    def init(self, parent):
    QWidget.init (self, parent)
    self.ListeBoutons = []
    self.currentSelection_ = -1

    def litSelection (self):
    return self.currentSelection_

    def setCurrentSelection (self, selection):
    self.currentSelection_ = -1
    for elem in self.ListeBoutons:
    if elem[1] == selection:
    self.currentSelection_ = selection

    def setSelectionId (self, Bouton, ident):
    self.ListeBoutons.append([Bouton, ident])

    def buttonToggled (self, checked):
    if checked:
    Bouton = self.sender()
    for elem in self.ListeBoutons:
    if elem[0] == Bouton:
    self.currentSelection_ = elem[1]

    currentSelection = Property(int, litSelection, setCurrentSelection, user = True)
    selectionChanged = Signal(int)

  • Hi jmelbye

    can u please elaborate how to provide Id for each and every radiobutton and then store in mdoel

  • Hi jmelbye

    can u please elaborate how to provide Id for each and every radiobutton and then store in mdoel

  • and also i get this error while exec
    error: 'QMap<Key, T>::iterator::operator bool() const [with Key = int, T = QRadioButton*]' is private

  • and also i get this error while exec
    error: 'QMap<Key, T>::iterator::operator bool() const [with Key = int, T = QRadioButton*]' is private

Log in to reply