Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QRadioButton group and QDataWidgetMapper

QRadioButton group and QDataWidgetMapper

Scheduled Pinned Locked Moved General and Desktop
7 Posts 4 Posters 4.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    jmelbye
    wrote on last edited by
    #1

    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:

    optiongroup.h
    @
    #ifndef OPTIONGROUP_H
    #define OPTIONGROUP_H

    #include <QWidget>
    #include <QMap>

    class QRadioButton;

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

    public:
    explicit OptionGroup(QWidget *parent = 0);

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

    signals:
    void selectionChanged(int selection);

    public slots:
    void buttonToggled(bool checked);

    private:
    int currentSelection_;
    QMap<int, QRadioButton*> buttonMap_;
    QMap<QRadioButton*, int> revButtonMap_;
    };

    #endif // OPTIONGROUP_H
    @

    optiongroup.cpp:
    @#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)
            iter.value()->setChecked(false);
    } else {
        iter.value()->setChecked(true);
        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());
    Q_ASSERT(btn);
    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.

    1 Reply Last reply
    0
    • R Offline
      R Offline
      rivimey
      wrote on last edited by
      #2

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

      1 Reply Last reply
      0
      • L Offline
        L Offline
        lvlvlvl
        wrote on last edited by
        #3

        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:
        elem[0].setChecked(True)
        self.currentSelection_ = selection

        def setSelectionId (self, Bouton, ident):
        self.ListeBoutons.append([Bouton, ident])
        Bouton.toggled[bool].connect(self.buttonToggled)

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

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

        1 Reply Last reply
        0
        • M Offline
          M Offline
          mananbhatt
          wrote on last edited by
          #4

          Hi jmelbye

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

          1 Reply Last reply
          0
          • M Offline
            M Offline
            mananbhatt
            wrote on last edited by
            #5

            Hi jmelbye

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

            1 Reply Last reply
            0
            • M Offline
              M Offline
              mananbhatt
              wrote on last edited by
              #6

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

              1 Reply Last reply
              0
              • M Offline
                M Offline
                mananbhatt
                wrote on last edited by
                #7

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

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved