Qt Signal Slot Lambda Functions
I’ve been asked multiple times how I would implement a signal / slot mechanism in modern C++. Here is the answer!
I believe the signal/slot mechanism has found its soul mate in C11 lambda functions. What’s this signal/slot thingy? If you don’t work in Qt you probably don’t care anyway but the fundamental communication mechanism between objects in the Qt framework is defined by signals (events that can be emitted) and slots (handlers for events). When the user clicks a button, the custom widget will emit a single clicked signal whose argument is the text of the button the user clicked. This class was mostly useful before lambda functions could be used as slots. The example above can be rewritten simpler without QSignalMapper by connecting to a lambda function.
What’s the Signal / Slot Pattern?
So basically it allows for event based inter-object communication. In my opinion it’s intuitive to use and produces easily readable code when used in a moderate amount. And the big plus: It can be added to your program with one simple template class!
There are many libraries around (refer to the linked Wikipedia article) implementing this pattern, but it’s so easy to implement on you own that I would recommend to do this without an additional dependency. All you need is the header I posted below. And it’s a good exercise.
The signal template class
Below you can find the entire class. Because this class is using variadic templates you can define signals which pass any kind of data to their slots. Basically you can create signals which allow for arbitrary slot signatures. The emit method will accept the same argument types you declared as template parameters for the Signal class. The class is documented with comments and should be quite understandable. Further below you will find two usage examples.
Simple usage
The example below creates a simple signal. To this signal functions may be connected which accept a string and an integer. A lambda is connected and gets called when the emit method of the signal is called.
When you saved the Signal class as Signal.hpp
and the above example as main.cpp
you can compile the example with:
And if you execute the resulting application you will get the following output:
Advanced usage
This example shows the usage with classes. A message gets displayed when the button is clicked. Note that neither the button knows anything of a message nor does the message know anything about a button. That’s awesome! You can compile this example in the same way as the first.
You may also connect member functions which take arguments (Thank you FlashingChris for pointing out how to do this without std::placeholders!). In the following example Alice and Bob may say something and the other will hear it:
Issues & next steps
There are two drawbacks in this simple implementation: It’s not threadsafe and you cannot disconnect a slot from a signal from within the slot callback. Both problems are easy to solve but would make this example more complex.
Using this Signal class other patterns can be implemented easily. In a follow-up post I’ll present another simple class: the Property. This will allow for a clean implementation of the observer pattern.
Have some fun coding events in C++!
Edit on 2020-10-19:
- Add move-copy-constructor and move-assignment-operator
- Add
emit_for_all_but_one
andemit_for
methods. - Remove previously added
std::forward
.
Qt Signal Slot Lambda Functions Examples
Please enable JavaScript to view the comments powered by Disqus.blog comments powered by Disqus- PyQt Tutorial
- PyQt Useful Resources
- Selected Reading
Unlike a console mode application, which is executed in a sequential manner, a GUI based application is event driven. Functions or methods are executed in response to user’s actions like clicking on a button, selecting an item from a collection or a mouse click etc., called events.
Widgets used to build the GUI interface act as the source of such events. Each PyQt widget, which is derived from QObject class, is designed to emit ‘signal’ in response to one or more events. The signal on its own does not perform any action. Instead, it is ‘connected’ to a ‘slot’. The slot can be any callable Python function.
In PyQt, connection between a signal and a slot can be achieved in different ways. Following are most commonly used techniques −
A more convenient way to call a slot_function, when a signal is emitted by a widget is as follows −
Suppose if a function is to be called when a button is clicked. Here, the clicked signal is to be connected to a callable function. It can be achieved in any of the following two techniques −
or
Example
In the following example, two QPushButton objects (b1 and b2) are added in QDialog window. We want to call functions b1_clicked() and b2_clicked() on clicking b1 and b2 respectively.
When b1 is clicked, the clicked() signal is connected to b1_clicked() function
Qt Signals And Slots Lambda
When b2 is clicked, the clicked() signal is connected to b2_clicked() function
Example
Qt Signal Slot Lambda Functions Diagram
The above code produces the following output −