📜 ⬆️ ⬇️

Connect Qt-signal with a simple function and lambda

Many programmers working with Qt4 probably had an obsessive desire to connect the signal sent by a certain QObject heir to a simple function that is not a slot or even a member of a certain class. However, if the entire project is built on objects (as it usually happens), and all of them are inherited from QObject, then adding a function slot to the right place is easy. And if not? If, for example, you do not want to inherit your QObject class from memory savings (or for other reasons), or does the slot take just 1 line and it would be easier and more convenient to write it as a lambda expression? Or do you, for a number of reasons, want to call a single function, which is not a member of a class, on a signal?

Faced with this problem, I decided to write a class that allows you to connect the signal not only with the function-slot, but also with the most ordinary function, and, with the support of C ++ 11, also with the lambda expression.

We write class SmartConnect


For starters, what should a class do? It must inherit from QObject and store a link to our function. Those. we associate a signal of any class with some SmartConnect slot, and SmartConnect already stores a link to our independent function or lambda expression, and calls it in its slot.

The most convenient solution would be to overload the SmartConnect designer — to reference different functions. Let it start to work with two types of signals - which pass void in the argument, as well as those that pass QString. Create a smartconnect.h file:
#include <QtCore>
')
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 the smartconnect.cpp itself:
#include <QtCore>
#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 called constructor, it selects the necessary internal slot and connects with it, and also saves a reference to our function. If desired, we can make support for signals with any arguments - just add a reference to the function with these arguments, the slot that the constructor accepts them. But externally, the use of the class will be all just.

We write a demo


Now create the main.cpp file:
#include <QtGui>
#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 is connected to the non-slot function, the other - with lambda expressions - and when you click on them, the corresponding messages are displayed. Now let's create a pro-file, do not forget to connect C ++ 11. At once I will say that this will require a new version of Qt, compiled 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

And finally, we compile and build 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 the class is simple and convenient, in some cases it can be very useful and actually simplify the code.

Source: https://habr.com/ru/post/171835/


All Articles