Welcome! Log In Create A New Profile

Advanced

Accessing object that emitted the signal

Announcements Last Post
Announcement SoC Curricula 09/30/2017 01:08PM
Announcement Demarcation or scoping of examinations and assessment 02/13/2017 07:59AM
Announcement School of Computing Short Learning Programmes 11/24/2014 08:37AM
Announcement Unisa contact information 07/28/2011 01:28PM
Accessing object that emitted the signal
May 07, 2010 04:28PM
How do I get a pointer to the object that emitted the signal in the slot that connects to the signal?

Language: C++
QApp->connect(sender, SIGNAL(sendFunction()), receiver, SLOT(receiveFunction())   void receiveFunction { //Somehow get the pointer to the sender sender->getsomething(); }

As far as I can remember in Delphi and Java the reference to the object is passed as a parameter? confused smiley
avatar Re: Accessing object that emitted the signal
May 07, 2010 05:51PM
Do you want this functionality just because it's available in other languages or does your design require it?

The reason I ask is because if the slot knows about the sender, it breaks the pattern and you might as well just call the receiving class' function directly from the sender.

Qt does provide such an ability. see the QObject documentation concerning the sender() function. Take care of the warnings though or try using the QSignalMapper class.

Before you decide to use this function though, try to see if you can change your design so that you don't have to.
Re: Accessing object that emitted the signal
May 07, 2010 06:31PM
Thank as always Rob thumbs up...It needs it at the moment, but there is a way around. Complicates my code a little more though. But I'll make it elegant once more smoking smiley. If you say breaks design, do you mean it causes classes to no longer be decoupled from each other?
avatar Re: Accessing object that emitted the signal
May 07, 2010 08:17PM
Indeed correct.

Consider this:

Language: C++ (QT)
class SendingClass : public QObject { Q_OBJECT public: SendingClass();   public slots: void someAction();   signals: void someSignal(); };   class ReceivingClass : public QObject { Q_OBJECT public: ReceivingClass();   public slots: void someSlot() { SendingClass *senderObject = qobject_cast<SendingClass *>(sender()); if (senderObject != 0){ senderObject->someAction(); } } };   int main(int argc, char **argv){ SendingClass sending; ReceivingClass receiving; connect(&sending, SIGNAL(someSignal()), &receiving, SLOT(someSlot()));   // .... more code }

ReceivingClass has to know about SendingClass thus there is a coupling here. SendingClass is still oblivious of ReceivingClass so the dependency is only one way. Also, what happens if you design some other class that needs to connect to the ReceivingClass' slot. The slot will not work for anything other than a SendingClass, so you might as well not bother with the signals/slots mechanism and call the functions directly.

If you need the cyclic nature of what you described, try splitting your sending class in two, one that handles the action that needs to be performed when the signal is being emitted, and the other to actually emit the signal.

You could also modify your code so that ReceivingClass::someSlot() emits a signal instead of trying to determine the sender and restricting it to SendingClass. This will maintain the independence of the two classes and allow substitution of some other class in the future that could do the work better and not break the code of ReceivingClass.

Language: C++ (QT)
class SendingClass : public QObject { Q_OBJECT public: SendingClass();   public slots: void someAction();   signals: void someSignal(); };   class ReceivingClass : public QObject { Q_OBJECT public: ReceivingClass();   signals: void reactionarySignal();   public slots: void someSlot() { emit reactionarySignal(); } };   int main(int argc, char **argv){ SendingClass sending; ReceivingClass receiving; connect(&sending, SIGNAL(someSignal()), &receiving, SLOT(someSlot())); connect(&receiving, SIGNAL(reactionarySignal()), &sending, SLOT(someAction()));   // .... more code }
Re: Accessing object that emitted the signal
May 08, 2010 10:05AM
Thanks that's very helpful...What I was trying to create was a class that represents a GUI display(Combination of buttons, text-fields etc.) and then handles signals that were emitted by the buttons, text-fields etc. So what I'm going to do now is separate the functionality into a GuiClass and GuiHandler(Which is actually correct, makes it more transparent). The code would then look something like the following:

Language: C++
class GuiClass { public: GuiClass(QWidget* aParent);   protected: //Gui object pointers SomeGuiClass *m_GuiPointer;   private: //Other member fucntions };   class GuiHandler : QObject { Q_OBJECT   public: GuiHandler();   public slots: void handleSignal(); };   int main(int argc, char *argv[]) { QApplication app(argc, argv);   QWidget rootWidget;   GuiClass sender(&rootWidget); GuiHandler receiver;   qApp->connect(&sender, SIGNAL(sender.m_GuiPointer.someSignal()), &receiver, SLOT(receiver.handleSignal()));   return app.exec(); }

My first question is, is this correct pattern wise? And then secondly is it okay to make use of the protected access specifier here, or is it better to use set and get methods. I'm always shaky on when it is okay...
avatar Re: Accessing object that emitted the signal
May 08, 2010 11:15AM
You're confusing SIGNAL() and SLOT() with actual functions, they're not. They're precompiler macros, so is qApp. After the precompiler's finished it's work, your line is sent to the compiler as:

Language: C++ (QT)
QCoreApplication::instance()->connect(&sender, "1,sender.m_GuiPointer.someSignal()", &receiver, "2,receiver.handleSignal()");

If there wasn't a transformation to a string, your compiler would have screamed at you for using a protected data member outside of a class function (m_GuiPointer is not public).

-----------------
It looks like you're trying to come up with a design that's already been thought of. Go look up the Model/View/Controller pattern. Qt has a modified form of the pattern where they combine View and Controller to give the Model/View API. Go have a read in the documentation.

In short, the model is the class or group of classes that are responsible for the data and modification/transformation of the data (ie the business logic of the program). The view is responsible for showing the data in a specific way (either on screen, in a printout, etc). The controller is there to act as a mediator between the view and the model. It handles user input, validation, etc. It's the only component of the pattern that knows about the other two.
Re: Accessing object that emitted the signal
May 08, 2010 12:06PM
LMAO...true that, didn't even realize. "She" most probable would kick my ass to! moody smiley Access specifiers 101: protected functions can only be used in subtypes..But in my defense its been a while since I've done some proper programming...I'll take the fact that I'm trying to create an already existing design pattern as a complement though smoking smiley. After all great minds think alike, right?...ha ha ha.

Anyways going to take a look now. I'm actually busy with question 3 on the assignment, again that is. Wasn't happy with my first attempt. Just seemed so bulky to put all the GUI stuff in a function in the cpp file containing main. Bit of a perfectionist when it comes to my programming.

On something else though. I just want to make sure I understand the observer pattern right in relation to QT's connect. Basically how I've formed it in my head; is you want a Subject class that uses the connect macro to connect two or more Observer classes's Signals and Slots together so that they can communicate when a event is emitted while still remaining decoupled, oblivious of each others existence.
Re: Accessing object that emitted the signal
May 11, 2010 09:24AM
Correction: QObject's function connect, not macro. But that makes use of signal and slot macros.
avatar Re: Accessing object that emitted the signal
May 11, 2010 09:20PM
Read my post again. I didn't say that connect was a macro at all.
Sorry, only registered users may post in this forum.

Click here to login