Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set specific values in a QSpinBox

Tags:

qt

qspinbox

I have a widget containing a QSpinBox. This widget also has a QVector<int> Values. What I would like to do is get the QSpinBox to display values issued from Values only.

At first I thought that a new slot and signal in my widget would do the trick, something like

slot :

void ChangeSomeValue()
{
    // QVector<int> Values;
    // int Index;
    int val = Values[ Index ];
    emit( SomeValueChanged( val ) );
}

connects :

connect( UI->MySpinBox, SIGNAL( valueChanged(int) ), this, SLOT( ChangeSomeValue() ) );
connect( this, SIGNAL( SomeValueChanged(int ) ), UI->MySpinBox, SLOT( setValue(int) ) );

But then several problems arise :

  1. QSpinBox emit another valueChanged after I call its setValue, resulting in an infinite loop (until my QVector explodes).
  2. I still have to find a way to keep track of Index, depending on which of the QSpinBox arrows was clicked (up or down... I don't even think this is possible).

So my solution, with its problems, seems to be a dead end. Any idea?. I'd like to stick to QSpinBox, if possible.

Thanks !

[EDIT]

Subclassing :

class SpinBox : public QSpinBox
{
    Q_OBJECT
public:
    explicit SpinBox(const QVector<int> & values, QWidget * parent = 0) :
        QSpinBox(parent),
        mValues(values),
        mIndex(0)
    {
        qSort(mValues);
        setMinimum(mValues.at(0));
        setMaximum(mValues.at(mValues.size() - 1));
        setValue(mValues.at(0));
    }

protected:
    void stepBy(int steps) // re-implementaion
    {
        mIndex += steps;
        mIndex = qBound(0, mIndex, mValues.size() - 1);
        setValue(mValues.at(mIndex));
    }

private:
    QVector<int>    mValues;
    int             mIndex;
};
like image 932
CTZStef Avatar asked Nov 29 '13 15:11

CTZStef


2 Answers

I Would suggest writing your own class to do it by sub-classing QAbstractSpinBox.

Maybe take a look at the accepted answer on this question: How to subclass QSpinBox so it could have int64 values as maxium and minimum

like image 72
Pete Avatar answered Nov 15 '22 09:11

Pete


QSpinBox emit another valueChanged after I call its setValue, resulting in an infinite loop (until my QVector explodes).

You can prevent this by using QObject::blockSignals(). Make sure to unblock signals afterwards.

I still have to find a way to keep track of Index, depending on which of the QSpinBox arrows was clicked (up or down... I don't even think this is possible).

Well, I suppose you can store the old value in a member variable, and when QSpinBox emits valueChanged(), you can compare the new to the old value to figure out whether the up or the down arrow was pressed.

That said, I don't know if that's enough to make QSpinBox behave like you want, correcting the value after it was changed once is a bit hacky. Subclassing QAbstractSpinbox might be better indeed.

like image 45
Thomas McGuire Avatar answered Nov 15 '22 09:11

Thomas McGuire