2
votes

With Qt 4.8 I create a number of input widgets (QSpinBox, QSlider) programmatically. In the end, I would like to have a single method to handle changes of any of these input widgets, ideally by index.

However, these widgets only have a Signal with parameter, e.g. valueChanged(int). This is not compatible with QSignalMapper()'s Slot map().

As it was pointed out in the comments, the connection does work!

    connect(    spinbox,        SIGNAL( valueChanged(int)  ),
                signalMapper,   SLOT(   map()            )
                );

Now I just need to get the value, but this cannot be done via the sender() method anymore, because this now is the SignalMapper.


Original question:

Is there another way besides (re)implementing QSignalMapper with additional parameters or a parameter-less valueChanged() for the widget or using objectName and QObject::sender() in order for the Slot to see which element changed (and get the new value)?

2
can't you just query the new value in the slot listening to the mapper (you can signal with more parameters than a slot takes) - ratchet freak
You don't need to repimplement QSignalMapper. Just create an instance of QSignalMapper and define mappings for it. It supports mapping of various datatypes, so you can define integers, strings, or even anything that casts to QObject*. What other information would you expect in the slot? - Googie
See this: stackoverflow.com/questions/24260394/how-works-qsignalmapper for how to correctly use QSignalMapper. This is really the best solution for what you need to do. - Googie
@Googie Yes, I would not mind using QSignalMapper, but my widgets don't have the equivalent to the clicked() method used in the example solution you posted. Or I still don't get it - could you post an example in an answer? - handle

2 Answers

1
votes

You can use QAbstractSpinBox::editingFinished() and QAbstractSlider::sliderReleased() as your signals, they are parameterless.

Unfortunately there is no parameterless version of QAbstractSlider::valueChanged() so if you want a signal emitted continuously as the slider moves, you may need to subclass QSlider and create it. E.g.

class MySlider : public QSlider
{
   ...
   private slots:
      void HandleValueChanged(int) { emit valueChanged(); }
   signals:
      void valueChanged();
};

MySlider::MySlider(...)
{
    connect(this, SIGNAL(valueChanged(int)), this, SLOT(HandleValueChanged(int)));
}

Though I admit, this may not be the most elegant solution.

0
votes

If I understand your question and what you have until now correctly, you are missing two parts.

mapper->setMapping(<spinbox>, <id or name or pointer to the spinbox);
connect(mapper, SIGNAL(mapped(<datatype you used in setMapping()>),
this, SLOT(HandleValueChanged(<datatype you used in setMapping()>)));

So the HandleValueChanged() slot will receive an identifier of your sender, then you can directly access the value of the sender with the appropriate getter. The method setMapping() takes either and integer, QString or a pointer to the widget itself as second argument. This is then forwarded via the mapped() signal of the mapper, so you can later identify which widget emitted the signal.