Application analysis of custom signal slot in QT + Example

Posted by KendersPlace on Sun, 30 Jan 2022 02:31:47 +0100

1. Use of custom signal slot in QT

The signal slot provided by Qt framework cannot meet the needs of our project in some specific scenarios. Therefore, we also design our own signal and slot and use connect() to connect the customized signal slot.

If you want to use a custom signal slot, first write a new class and let it inherit some standard classes of Qt. If the class we write ourselves wants to use the signal slot mechanism in Qt, the following conditions must be met:

  • This class must derive from the QObject class or its subclass
  • Add Q to the header file of the definition class_ Object macro

1.1 custom signal

requirement:
1. A signal is a member function of a class
2. The return value is of void type
3. The name of the signal can be specified according to the actual situation
4. Parameters can be specified at will, and signals can also be overloaded
5. Signals need to be declared with the keywords signals, which are similar to public and other keywords
6. The signal function only needs to be declared, not defined (there is no function body implementation)
7. Send custom signal in the program: the essence of sending signal is to call the signal function

  • Habitually add keyword before signal function: emit
  • emit is just a statement that the signal will be sent. It has no special meaning
  • Underlying emit == #define emit

Examples

class Test : public QObject
{
    Q_OBJECT
signals:
    void testsignal();
	// The function of parameter is data transmission. Whoever calls the signal function will specify the actual parameter
	// The arguments are eventually passed to the slot function
    void testsignal(int a);
};

1.2 custom slot

Slot function is the signal processing action. The custom slot function is written in the same way as the custom ordinary function.

requirement:

  1. The return value is of type void
  2. Slots are also functions, so overloading is also supported
  • How many parameters the slot function needs to specify depends on the number of parameters of the connected signal
  • The parameters of the slot function are used to receive the data sent by the signal, and the data sent by the signal is the parameters of the signal
  • give an example:
    Signal function: void testsig(int a, double b);
    Slot function: void testlot (int a, double B);
  • Summary:
    The parameters of the slot function should correspond to the number and type of parameters of the corresponding signal one by one
    The parameters of the signal can be greater than or equal to the number of parameters of the slot function = = the data transmitted by the signal is ignored
    Signal function: void testsig(int a, double b);
    Slot function: void testlot (int a);
    Here, the slot function only accepts the first parameter in the signal function
  1. Type of slot function in Qt:
    -Member function of class
    -Global function
    -Static function
    -lambda expression (anonymous function)
  2. Slot functions can be declared with keywords: slots (slots in Qt5 can be omitted)
    - public slots:
    - private slots:
    - protected slots:
// give an example
// All three functions in the class can be used as slot functions
class Test : public QObject
{
public:
    void testSlot();
    static void testFunc();

public slots:
    void testSlot(int id);
};

1.3 example of custom signal slot

Now there is a scene where my girlfriend is hungry and I invite her to dinner. What should I do to realize this function
First, specify the sender, receiver, signal and slot

  • Sender: girlfriend
  • Receiver: I
  • Signal: hungry
  • Slot: invite her to dinner

ok, with this clear, we can start writing code

First create two classes, GirlFriend and Me
Qt Creator will automatically add header files and CPP files for us. The directory structure is shown in the figure below

  1. In the GirlFriend class, add the signal hungry. The code is as follows
#ifndef GIRLFRIEND_H
#define GIRLFRIEND_H

#include <QObject>

class GirlFriend : public QObject
{
    Q_OBJECT
public:
    explicit GirlFriend(QObject *parent = nullptr);

signals:
    void hungry();

};

#endif // GIRLFRIEND_H

Note the signals keyword in the figure. This is the place used to define the signal. The signal function only needs to be defined, not implemented!

  1. Add the slot function eat() in the Me class;
#ifndef ME_H
#define ME_H

#include <QObject>

class Me : public QObject
{
    Q_OBJECT
public:
    explicit Me(QObject *parent = nullptr);

    // Slot function
public slots:
    // Slot function
    void eat();

};

#endif // ME_H

be careful!
The main purpose of using public slots here is to remind developers that this is a slot function. In fact, you don't need to use public slots alone. You can directly put this slot function into public. Like ordinary functions, slot functions not only need to be defined, but also need to be implemented.

  1. To Me Implement the slot function eat() of Me class in CPP
#include "me.h"
#include <QDebug>
Me::Me(QObject *parent) : QObject(parent)
{

}

void Me::eat()
{
    qDebug() << "Take you to spicy hot...";
}

ok, now that the slot function and signal function have been defined and implemented, how to realize the event response? A simple idea is to set a button, click the button to send a signal: hungry, and then let eat () respond

  1. Add a button called hungry to the mainwindow

    If it appears in MainWindow In CPP, I can't recognize this button. Please refer to my blog
    The problem that the newly added control in Qt project ui file is not recognized in the code is solved

  2. After adding this button, we need to add two member pointers to the mainwindow class

  3. In MainWindow CPP is bound through the connect function

Here I'll review the connect() function in Qt again

QMetaObject::Connection QObject::connect(
    	const QObject *sender, PointerToMemberFunction signal, 
        const QObject *receiver, PointerToMemberFunction method, 
		Qt::ConnectionType type = Qt::AutoConnection);
- parameter:
	- sender: Signaled object
	- signal: belong to sender object, The signal is a function, The type of this parameter is a function pointer, Signal function address
    - receiver: Signal receiver
	- method: belong to receiver object, When detected sender Issued signal signal, 
              receiver Object call method Method, the processing action after the signal is sent
                  
// The connect function is registered relative to the signal processing action
// The signal of the sender object calling the conenct function is not generated, so the method of the receiver object will not be called
// The method slot function is essentially a callback function. The timing of the call is the execution of the Qt framework after the signal is generated.
// The sender and recever pointers in connect must be instantiated, otherwise conenct will not succeed
connect(const QObject *sender, &QObject::signal, 
        const QObject *receiver, &QObject::method);

After knowing the usage of the connect function, let's start with my_girl send signal, M_ Me (m_girl and m_me are the two member pointers added above) accept signals and bind them together
In MainWindow Add the following statement to the constructor of CPP

	m_me = new Me;
    m_girl = new GirlFriend;

    // The hungry signal is user-defined and cannot be sent by the framework, because the framework does not know the existence of this signal at all. Therefore, the user needs to send this signal at a specific time
    connect(m_girl,&GirlFriend::hungry,m_me,&Me::eat);
    

Note the note above connect
The hungry signal is user-defined and cannot be sent by the framework, because the framework does not know the existence of this signal at all. Therefore, the user needs to send this signal at a specific time

The simple understanding is that your girl can't automatically send the signal of hungry, because Qt framework doesn't know the signal of hungry. You need to click the button to make the girl send the signal, so you need another function called hungrySlot(), which is used to click the button to make the girl send the signal

  1. Define and implement the function hungrySlot in mainwindow. I won't let go of the code of function definition. Let's define it ourselves
    The following is the implementation code
void MainWindow::hungrySlot()
{
    // Transmit custom signal
    emit m_girl->hungry();
}

be careful!
The emit keyword here is optional, but it is recommended that you write it to remind developers that this function is a function that emits custom signals

  1. Now is the most critical step. Bind the button to the function that girl sends the hungry signal. The event that the button is clicked can be sent by the framework, so we don't need to worry

Bind in the constructor of mainwindow. The code is as follows

connect(ui->hungry,&QPushButton::clicked,this,&MainWindow::hungrySlot);

Custom slot, OK

Next, let's test run

  1. Operation results


It can be seen that every time I click the Hungry button, "take you to spicy hot" will appear at the bottom, which proves that our custom signal slot is successful

It's not easy to write. If you reprint something, remember to mark it~

Topics: C++ Qt Qt5