Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using emit vs calling a signal as if it's a regular function in Qt

Tags:

c++

qt

Let's say I have this signal:

signals:     void progressNotification(int progress); 

I only recently learned about the emit keyword in Qt. Until now, I used to execute signals by just calling them like a regular function. So instead of:

emit progressNotification(1000 * seconds); 

I would write:

progressNotification(1000 * seconds); 

Calling them like that seemed to work, and all the connected slots would execute, so does using the emit keyword cause a different behaviour, or is it just syntactic sugar?

like image 856
sashoalm Avatar asked Apr 15 '12 08:04

sashoalm


People also ask

What is the use of Emit in Qt?

emit is just syntactic sugar. If you look at the pre-processed output of function that emits a signal, you'll see emit is just gone. The "magic" happens in the generated code for the signal emitting function, which you can look at by inspecting the C++ code generated by moc.

How do you emit signals in Qt?

In Qt, we have an alternative to the callback technique: We use signals and slots. A signal is emitted when a particular event occurs. Qt's widgets have many predefined signals, but we can always subclass widgets to add our own signals to them. A slot is a function that is called in response to a particular signal.

Can we connect signal to signal in Qt?

This ensures that truly independent components can be created with Qt. You can connect as many signals as you want to a single slot, and a signal can be connected to as many slots as you need. It is even possible to connect a signal directly to another signal.


2 Answers

emit is just syntactic sugar. If you look at the pre-processed output of function that emits a signal, you'll see emit is just gone.

The "magic" happens in the generated code for the signal emitting function, which you can look at by inspecting the C++ code generated by moc.

For example a foo signal with no parameters generates this member function:

void W::foo() {     QMetaObject::activate(this, &staticMetaObject, 0, 0); } 

And the code emit foo(); is pre-processed to simply foo();

emit is defined in Qt/qobjectdefs.h (in the open-source flavor of the source anyway), like this:

#ifndef QT_NO_EMIT # define emit #endif 

(The define guard is to allow you to use Qt with other frameworks that have colliding names via the no_keywords QMake config option.)

like image 185
Mat Avatar answered Oct 05 '22 13:10

Mat


After 18 months ... I started with comments under @Mat's answer, and was running out of room quickly. Thus the answer.

IMO emit is neither syntactic sugar nor a simple keyword in the sense that

  1. It generates code (as explained by @Mat above),
  2. It helps the connect mechanism recognize that indeed it is a signal, and
  3. It makes your signal part of a "bigger" system, where signals and responses (slots) can be executed synchronously or asynchronously, or queued, depending on where and how the signal got emitted. This is an extremely useful feature of the signal/slot system.

The entire signal/slot system is a different idiom than a simple function call. I believe it stems from the observer pattern. There is also a major difference between a signal and a slot: a signal does not have to be implemented, whereas a slot must be!

You are walking down the street and see a house on fire (a signal). You dial 911 (connect the fire signal with the 911 response slot). The signal was only emitted, whereas the slot was implemented by the fire department. May be imprecise, but you get the idea. Let's look at the example of OP.

Some backend object knows how much progress has been made. So it could simply emit progressNotification(...) signal. It is up to the class that displays the actual progress bar, to pick up this signal and execute on it. But how does the view connect to this signal? Welcome to Qt's signal/slot system. One can now conceive of a manager class (typically a widget of sorts), which consists of a view object and a data computation object (both being QObjects), may perform connect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress).

Let's not get into the design aspects of the manager class, but suffice it to say that this is where signal/slot system shines. I can focus on designing a very clean architecture for my application. Not always, but often times, I find that I merely emit signals but implement slots.

If it is possible to use/call a signal method without ever emitting it, then it necessarily implies that you never needed that function as a signal in the first place.

like image 36
NameRakes Avatar answered Oct 05 '22 13:10

NameRakes