PDA

View Full Version : is there anyway to know witch object sends a signal to a slot?



Alex22
3rd December 2015, 12:39
Hi

There are two objects of a class(obj1 , obj2). These objects use same signal and slot like this:


connect(obj1, SIGNAL(sgnl()), SLOT(slt()));
connect(obj2, SIGNAL(sgnl()), SLOT(slt()));

//sgnl and slt are created by myself.

I need when sgnl() signal is send from obj1, the slt() slot can know this and use obj1 address and also when sgnl() signal is send from obj2, the slt() slot can know this and use obj2 address.

Thanks for any helps.

Scope
3rd December 2015, 13:20
http://doc.qt.io/qt-5/qobject.html#sender
http://doc.qt.io/qt-5/qsignalmapper.html

Qiieha
3rd December 2015, 14:33
void MyClass::slt(){
Object* obj = (QObject*) sender(); //sender() holds the instance of the sender
}

Alex22
3rd December 2015, 16:22
void MyClass::slt(){
Object* obj = (QObject*) sender(); //sender() holds the instance of the sender
}



Realy thanks Qiieha, this works so nice!!!
but we cast it to Object* and not to QObject*.

Object* obj = (Object*) sender()

yeye_olive
3rd December 2015, 16:51
Yes, QObject::sender() works but it really is a hack that defeats modularity. QSignalMapper is the Right Way.

Alex22
3rd December 2015, 18:01
Yes, QObject::sender() works but it really is a hack that defeats modularity. QSignalMapper is the Right Way.

@yeye_olive, what do you mean about hack and modularity defeating?

Qiieha
3rd December 2015, 19:32
You're welcome. yeye_olive is right. The doc of QObject::sender() says the same. You'll get in troubles, if you use this method in a multi-threaded program using direct connections. So it's safer and better to use QSignalMapper.

Look at the doc of QSignalMapper. There's an example, which solves the same thing as you want to achieve.

yeye_olive
3rd December 2015, 19:39
The documentation says it all:

This function violates the object-oriented principle of modularity.
The whole point of signals and slots is that a QObject need not worry if/how it is connected to other QObjects. The user calling QObject::connect() is the one whose program logic depends on the connections. QObject::sender() violates this principle because the behavior of a QObject depends on which object emitted the signal connected to its slot, which limits its reusability as a component. Everything the receiving QObject needs to know to execute its slots should be encoded in the slot's parameters, not hidden in sender(). QSignalMapper allows you to do just that.

Alex22
3rd December 2015, 20:15
So much thanks!!!

anda_skoa
4th December 2015, 15:40
And even if you cast, don't ever use C-Style casts in C++ programs.

Cheers,
_

Alex22
4th December 2015, 19:44
And even if you cast, don't ever use C-Style casts in C++ programs.

Cheers,
_

@anda_skoa, Thanks for your helping but I can not understand what you mean. I used QSignalMapper and I need to cast it. Is there any problem by casting like this:


QSignalMapper *_signalmapper = new QSignalMapper(this);
.
.
.
QComboBox * cmb = new QComboBox(this);
cmb = (QComboBox*)(_signalmapper->mapping(4));

Scope
4th December 2015, 20:22
What you doing? Please look for example in doc QSignalMapper



ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
: QWidget(parent)
{
signalMapper = new QSignalMapper(this);

QGridLayout *gridLayout = new QGridLayout;
for (int i = 0; i < texts.size(); ++i) {
QPushButton *button = new QPushButton(texts[i]);
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
signalMapper->setMapping(button, texts[i]);
gridLayout->addWidget(button, i / 3, i % 3);
}

connect(signalMapper, SIGNAL(mapped(QString)),
this, SIGNAL(clicked(QString)));

setLayout(gridLayout);
}


adjust as needed.

http://doc.qt.io/qt-5/qsignalmapper.html

Alex22
4th December 2015, 20:51
@Scope, I need to know which signal sends each time. by _signalmapper->mapping() I can know (this returns its address but must be casted).
@anda_skoa@ But has told something about casting that i could not understand. Now my project is working by QSignalmapper and is like that example. anyway thanks for your answering

Scope
4th December 2015, 21:18
Ok, you should use http://doc.qt.io/qt-5/qobject.html#qobject_cast for QObject class or class which derived from QObject.

In other case use c++ style cast like as static_cast - is safer.

anda_skoa
5th December 2015, 11:31
@anda_skoa, Thanks for your helping but I can not understand what you mean.

Don't use C casts, i.e.


ResultType *result = (ResultType*)input;


If you are absolutely certain that input is of type ResultType, then use a static_cast


ResultType *result = static_cast<ResultType*>(input);


If you are not certain, use a checking cast, e.g. a qobject_cast for QObject based classed or dynamic_cast in general.
Both will check the validity of the cast and return a null pointer if the cast is not possible.

Cheers,
_