Connect Qt signal with simple function and lambda
Faced with this problem, I decided to write a class that allows you to connect a signal not only with a function slot, but also with the most ordinary function, and with C ++ 11 support, also with a lambda expression.
Writing a SmartConnect Class
For starters, what should a class do? It should inherit from QObject and store a link to our function. Those. we associate a signal of a class with some SmartConnect slot, and already SmartConnect stores a link to our independent function or lambda expression, and calls it on its own slot.
The most convenient solution is to overload the SmartConnect constructor - to link to various functions. Let it start by working with two types of signals - which pass void in the argument, as well as those that pass QString. Create a smartconnect.h file:
#include
class SmartConnect: public QObject
{
Q_OBJECT
void (* pVoidFunc) (void);
void (* pQStringFunc) (QString);
public:
SmartConnect (QObject * sender, const char * signal, void (* pFunc) (void));
SmartConnect (QObject * sender, const char * signal, void (* pFunc) (QString));
private slots:
void voidSlot ();
void QStringSlot (QString str);
};
Then - actually smartconnect.cpp:
#include
#include "smartconnect.h"
SmartConnect :: SmartConnect (QObject * sender, const char * signal, void (* pFunc) ()) {
pVoidFunc = pFunc;
QObject :: connect (sender, signal, this, SLOT (voidSlot ()));
}
SmartConnect :: SmartConnect (QObject * sender, const char * signal, void (* pFunc) (QString)) {
pQStringFunc = pFunc;
QObject :: connect (sender, signal, this, SLOT (QStringSlot (QString)));
}
void SmartConnect :: voidSlot () {
pVoidFunc ();
}
void SmartConnect :: QStringSlot (QString str) {
pQStringFunc (str);
}
As you can see, the class is really smart - depending on the constructor called, it selects the desired internal slot and connects to it, and also saves a link to our function. If desired, we can make support for signals with any arguments - just add a link to the function with these arguments, the slot that accepts them and the constructor. But outwardly using the class will be all as simple as that.
Writing a demo
Now create the main.cpp file:
#include
#include "smartconnect.h"
void onClick () {
qDebug () << "Hello from void onClick ()";
}
int main (int argc, char * argv []) {
QApplication app (argc, argv);
QPushButton button1 ("button1");
button1.show ();
SmartConnect smartConnect1 (& button1, SIGNAL (clicked ()), onClick);
QPushButton button2 ("button2");
SmartConnect smartConnect2 (& button2, SIGNAL (clicked ()), [] () {qDebug () << "Hello from lambda";});
button2.show ();
return app.exec ();
}
Here we create 2 buttons, one of which connects to the non-slot function, the other to the lambda expression, and when you click on them, the corresponding messages are displayed. Now let's create a pro-file, not forgetting to connect C ++ 11. I must say right away that this will require a new version of Qt, assembled under the same compiler that supports C ++ 11. Otherwise, the lambda example will not work. Create the main.pro file:
QT + = gui
TEMPLATE = app
CONFIG + = release
SOURCES + = main.cpp
smartconnect.cpp
HEADERS + = smartconnect.h
CONFIG + = console
QMAKE_CXXFLAGS + = -std = gnu ++ 11
Finally, compile and compile our example:
qmake main.pro -o Makefile
make
If desired, the class can be improved, for example, add disconnect to it, if necessary. As you can see, using a class is simple and convenient, in some cases it can be very useful and really simplify the code.