I basically have multiple events signals which I want to connect to the same slot. What I want to know is how can I pass string based parameters to that same slot so that the slot knows which is this signal coming from. One alternative is to make as many slots as there are signals and then connect them in a 1:1 manner, but this is efficient, considering that the code for all the processing is very similar. I tried doing this but I'm getting some errors:
connect(selecter1,SIGNAL(selected(QString)),this,SLOT(backgroundTypeChoiceMade(QString)));
connect(button1,SIGNAL(clicked()),this,SLOT(backgroundTypeChoiceMade("button1")));
connect(button2,SIGNAL(clicked()),this,SLOT(backgroundTypeChoiceMade("button2")));
The error is related to the parameters I'm passing in the last 2 commands .. And backgroundTypeChoiceMade
is declared like this:
void backgroundTypeChoiceMade(QString);
Can someone tell me what the error is in the above code ?
Four methods. One doesn't suck.
QSignalMapper
. Works, but makes for messy code.sender()
-compare. Can handle dynamic senders, but is still kinda ugly.Especially when you're using a small number of signals and sender types and when the senders are dynamically generated, subclassing the sender is the cleanest way. This lets you overload the existing signals to contain whatever parameters you need.
And now, wiring up the signals and slots just works:
and the extra code is out-of-sight in a subclass you'll never have to touch again.
See http://doc.qt.digia.com/qq/qq10-signalmapper.html#thesubclassapproach for an example implementation of subclassing
QPushButton
to emitclicked(int)
signals. Also discusses all four methods - named slots ("the trivial solution"), sender(), subclassing, and signal mapper.Caveat: Obviously works best for small numbers of sender types. But that's usually the case. And in that case, it's worth it.
What is inefficient about using separate slots? If there's commonality in the slot handlers then move that into a function, e.g. extending ereOn's example:
You can't pass constants to
connect()
because the effective parameters are deduced at execution time, not compile time.However, while this is against the
OO
principle, you can useQObject::sender()
which gives a pointer to the emitterQObject
.Example below:
If you have many buttons, you may also use a QSignalMapper by providing an identifier for each button.
You can use QSignalMapper. Although the QSignalMapper is the answer to your question, I think jon hanson's answer is the way you should take. You get much more cleaner code that way.
You can now really bind a value when connecting. Qt5 added support for that.
Example:
See more info.
NB: you can of course use std::bind or boost::bind instead of tr1::bind.
If you really don't want to use QSignalMapper, you could do something like this:
but QSignalMapper is just as easy...