2

I'm writig a code using qt libraries, in which I need to get the value of a spin box (by a signal) just before it changes.

I've got:

QSpinBox spinBoxWidth:
QSpinBox spinBoxScale;

I want to connect a signal from spinBoxWidth to spinBoxScale, so that the value of SpinBoxScale is always "the Value of SpinBoxWidth after changing" to "its value before changing".

(Scale = width_new/width_old)

I didn't find any slot in Qt which returns the old value of a spin box while changing the value. Can I somehow write a slot for that?

Best Regards

A.3dhgi
  • 95
  • 2
  • 7
  • Why don't you just cache the old value manually? Every time the spinBoxWidth is changed use the new value/cache value and then update the cache value to the new value. – A.Fagrell May 03 '16 at 10:25

3 Answers3

3

There are two ways of doing this:

  • Catch the change before it happens and store the old value using the event system (QKeyEvent, QMouseEvent). This is error-prone, as the value of spinBoxWidth can be set manually.
  • Connect spinBoxWidth's valueChanged(int) signal to a slot and reference the last value it was called with. I recommend this method.

Try something like this:

class MonitoringObject : public QObject
{
    Q_OBJECT
    int lastValue;
    int currentValue;
    ...
public Q_SLOTS:
    void onValueChanged(int newVal)
    {
        lastValue = currentValue;
        currentValue = newVal;
        if (lastValue == 0) //catch divide-by-zero
            emit ratioChanged(0);
        else
            emit ratioChanged(currentValue/lastValue);
    }
Q_SIGNALS:
    void ratioChanged(int);

After your signals are connected, the flow should look like this:

  • spinBoxWidth emits valueChanged(int)
  • MonitoringObject::onValueChanged(int) is invoked, does its work and emits ratioChanged(int)
  • spinBoxScale receives the signal in its setValue(int) slot and sets the appropriate value.
jonspaceharper
  • 4,207
  • 2
  • 22
  • 42
  • Yes, that was a good idea, although ratioChanged should emit the value in "double": rationChanged(double). – A.3dhgi May 04 '16 at 10:29
  • Ah. Your provided code has a regular spinbox as the receiver, not a `QDoubleSpinBox`. – jonspaceharper May 04 '16 at 12:58
  • @JonHarper Can you elaborate more on this. Like can you write out the signal/slot connection? And why does the `onValueChanged()` get invoked? I thought it was not a function for any part of the Qt classes. – reddy Aug 03 '18 at 08:46
1

The easiest way is probably a lambda that caches the value of valueChanged for the next call:

auto const width = new QSpinBox();

width->setValue(200);

connect(width, &QSpinBox::valueChanged,
    [prev_value = width->value()](int const value) mutable {
        auto const scale = double(value) / double(prev_value);

        // do stuff

        prev_value = value;
    });
Benjamin Buch
  • 4,752
  • 7
  • 28
  • 51
  • This solution is really cool: don't need to add a member variable to store the previous value. – gambr Nov 22 '22 at 15:49
0

I believe there is no specific signal to the "value before change" because you can always store it from the previous signal "onValueChanged()" you received.

So the basic idea would be:

  1. First time, receive signal onValueChanged(value) and store the value value_old;
  2. Next time you receive the signal, you can compute you scale!value/value_old;
  3. Then you can send a new signal, or directly modify the object with the new value.

You can derived your own version of QSpinBox including this code or implemented in the class it has to receive the signal. It depends on your architecture.

Daniel GL
  • 1,229
  • 11
  • 24