In the Qt world, what is the difference of events and signal/slots?
Does one replace the other? Are events an abstraction of signal/slots?
Events are something that happened to or within an object. In general, you would treat them within the object's own class code. Signals are emitted by an object. The object is basically notifying other objects that something happened.
It is generally unsafe to provide slots in your QThread subclass, unless you protect the member variables with a mutex. On the other hand, you can safely emit signals from your QThread::run() implementation, because signal emission is thread-safe.
Qt's event loop starts the moment the underlying application's exec() function gets called. Once started, the loop repeatedly checks for something to happen in the system, such as user-input through keyboard/mouse.
Event loop means that your code is continuously running, think about it as being refreshed every time, so changes will be seen and made continuously based off your cases you have. Directly connected slots don't go to the event queue, only queued connections.
In Qt, signals and events are both implementations of the Observer pattern. They are used in different situations because they have different strengths and weaknesses.
First of all let's define what we mean by 'Qt event' exactly: a virtual function in a Qt class, which you're expected to reimplement in a base class of yours if you want to handle the event. It's related to the Template Method pattern.
Note how I used the word "handle". Indeed, here's a basic difference between the intent of signals and events:
The difference is that when you "handle" the event, you take on the responsibility to "respond" with a behavior that is useful outside the class. For example, consider an app that has a button with a number on it. The app needs to let the user focus the button and change the number by pressing the "up" and "down" keyboard keys. Otherwise the button should function like a normal QPushButton
(it can be clicked, etc). In Qt this is done by creating your own little reusable "component" (subclass of QPushButton
), which reimplements QWidget::keyPressEvent
. Pseudocode:
class NumericButton extends QPushButton private void addToNumber(int value): // ... reimplement base.keyPressEvent(QKeyEvent event): if(event.key == up) this.addToNumber(1) else if(event.key == down) this.addToNumber(-1) else base.keyPressEvent(event)
See? This code presents a new abstraction: a widget that acts like a button, but with some extra functionality. We added this functionality very conveniently:
keyPressEvent
a signal, we would need to decide whether to inherit QPushButton
or just externally connect to the signal. But that would be stupid, since in Qt you're always expected to inherit when writing a widget with a custom behavior (for good reason - reusability/modularity). So by making keyPressEvent
an event, they convey their intent that keyPressEvent
is just a basic building block of functionality. If it were a signal, it'd look like a user-facing thing, when it's not intended to be.keyPressEvent
were a signal.The design of Qt is well thought out - they made us fall into the pit of success by making it easy to do the right thing and hard to do the wrong thing (by making keyPressEvent an event).
On the other hand, consider the simplest usage of QPushButton
- just instantiating it and getting notified when it's clicked:
button = new QPushButton(this) connect(button, SIGNAL(clicked()), SLOT(sayHello())
This is clearly meant to be done by the user of the class:
QPushButton
every time we want some button to notify us of a click, that would require a lot of subclasses for no good reason! A widget that always shows a "Hello world" messagebox
when clicked is useful only in a single case - so it's totally not reusable. Again, we have no choice but to do the right thing - by connecting to it externally.clicked()
- or connect several signals to sayHello()
. With signals there is no fuss. With subclassing you would have to sit down and ponder some class diagrams until you decide on an appropriate design.Note that one of the places QPushButton
emits clicked()
is in its mousePressEvent()
implementation. That doesn't mean clicked()
and mousePressEvent()
are interchangable - just that they're related.
So signals and events have different purposes (but are related in that both let you "subscribe" to a notification of something happening).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With