The concept of signal slots
Signal functions and slot functions are new features of Qt based on C++, similar to callback mechanisms in other languages
The use of signal slots is simpler, and communication between different component objects can be easily realized
It can be understood that the signal slot mechanism is: "If the A object..., then the B object..."
Two prerequisites for using signal slots:
- The communication object must be derived from QObject
- The beginning of the class must have the Q_OBJECT macro
function prototype
The connection of the signal slot is mainly realized through a static member function in the QObject class:
Most of the parameters with their own default values ββββcan be ignored
The fifth parameter here is not considered, which refers to a connection method - automatic connection
QObject::connect(const QObject * sender, const char * signal, const QObject * receiver, const char * method) [static]
Parameter 1: Emitter object - the object representing the cause
Parameter 2: Signal function, when the cause is triggered, the emitter emits a signal function, which requires SIGNAL() package
Parameter 3: Receiver object - represents the object that caused the result
Parameter 4: slot function, the specific function function executed by the receiver, that is, the result triggers the function call, which needs to be wrapped by SLOT()
In fact, the slot function is a special member function
Three ways of signal slot connection
In order to facilitate the step-by-step explanation, the signal-slot connection is divided into three ways from simple to complex
Self-contained signal → self-contained slot
Self-contained signal → custom slot
custom-signal → slot
method one
Self-contained signal → self-contained slot
This method does not require programmers to manually write any function definitions, just find the corresponding function connection in the API document
[Example] Click the button to close the window
Parameter 1: Emitter, often a noun - button object Parameter 2: Signal function, often a past tense verb - clicked function Parameter 3: Receiver, often a noun - window object Parameter 4: Slot function, often a verb - close function
code show as below:
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> // button header file #include <QPushButton> class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); private: // declared in the header file QPushButton *btn; }; #endif // DIALOG_H
dialog.cpp
#include "dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent) { // Resize the window in the constructor resize(300, 300); // Define the button in the constructor btn = new QPushButton("closure", this); // Set button position and width and height (x,y,w,h) btn->setGeometry(50, 50, 100, 50); // signal slot connection // QObject::connect(btn, SIGNAL(clicked()), this, SLOT(close())); // The base class function is called in the derived class, and the scope qualifier can be omitted if there is an inheritance relationship //overriding signal-slot connections connect(btn, SIGNAL(clicked()), this, SLOT(close())); } Dialog::~Dialog() { delete btn; }
main.cpp
#include "dialog.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Dialog w; // show() is also a slot function, so the slot function is a special member function w.show(); return a.exec(); }
way two
Self-contained signal → custom slot
the most used method
[Example] Click the button to move the window to the lower right corner by 10√2 pixels, and output debugging information at the same time
Parameter 1: button object Parameter 2: clicked function Parameter 3: window object Parameter 4: custom slot function `mySlot`
code show as below:
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QPushButton> #include <QDebug> class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); private: QPushButton* btn; // 1. Declare slot function (law of least privilege) private slots: // Scientific name: CamelCase // The first word is all lowercase, and the first letter of each subsequent word is capitalized void mySlot(); }; #endif // DIALOG_H
dialog.cpp
#include "dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent) { resize(200, 200); btn = new QPushButton("customize", this); btn->move(50, 50); // 3. Connect the signal slot connect(btn, SIGNAL(clicked()), this, SLOT(mySlot())); } // 2. Define the slot function void Dialog::mySlot() { // First get the coordinates of the current window int x = this->x(); int y = this->y(); // moving window move(x+10, y+10); // Output the position coordinates after the move qDebug() << this->x() << "," << this->y(); } Dialog::~Dialog() { delete btn; }
main.cpp
#include "dialog.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Dialog w; w.show(); return a.exec(); }
Running results after three clicks
Starting E:\QT\Tools\QtCreator\bin\build-qtday1_4-Desktop_Qt_5_2_1_MinGW_32bit-Debug\debug\qtday1_4.exe... 862 , 399 872 , 409 882 , 419 892 , 429 E:\QT\Tools\QtCreator\bin\build-qtday1_4-Desktop_Qt_5_2_1_MinGW_32bit-Debug\debug\qtday1_4.exe exited with code 0
way three
custom-signal → slot
Only in a few cases, you need to use custom signals, the following example is forced to use custom signals to complete
[Example] Click the button to close the window
Parameter 1: button object Parameter 2: clicked function Parameter 3: window object Parameter 4: custom slot function `mySlot`
code show as below:
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QPushButton> #include <QDebug> class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); private: QPushButton* btn; // 1. Declare slot function (law of least privilege) private slots: // Scientific name: CamelCase // The first word is all lowercase, and the first letter of each subsequent word is capitalized void mySlot(); // 3. The signal function has no permission signals: void mySignal(); }; #endif // DIALOG_H
dialog.cpp
#include "dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent) { resize(200, 200); btn = new QPushButton("chicken butcher knife", this); btn->move(50, 50); // 3. Connect the signal slot connect(btn, SIGNAL(clicked()), this, SLOT(mySlot())); // 5. Connect custom signal connect(this, SIGNAL(mySignal()), this, SLOT(close())); } // 2. Define the slot function void Dialog::mySlot() { qDebug() << "emit a custom signal"; // 4. Emit a custom signal function, the signal function has no call, no function body emit mySignal(); } Dialog::~Dialog() { delete btn; qDebug() << "window is closed"; }
main.cpp
#include "dialog.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Dialog w; w.show(); return a.exec(); }
operation result
Starting E:\QT\Tools\QtCreator\bin\build-qtday1_4-Desktop_Qt_5_2_1_MinGW_32bit-Debug\debug\qtday1_4.exe... emit a custom signal window is closed E:\QT\Tools\QtCreator\bin\build-qtday1_4-Desktop_Qt_5_2_1_MinGW_32bit-Debug\debug\qtday1_4.exe exited with code 0
Parameter passing
Programming Prerequisites
QPushButton of text : QString The attribute represents the displayed text, and the corresponding getter with setter for: getter: QString text() const setter: void setText(const QString & text) setter The function is not a slot function, so a custom slot function is required, which is called in the custom slot function text attribute setter function to change its value
global parameters
Parameter passing in a class can be through member variables or static local variables, etc.
[Example] Click the button, the number of clicks of the current button is displayed on the button
Ideas:
Member variable code example: Recommended
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QPushButton> class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); private: QPushButton* btn; // count member variable int count;// (1) You can assign the initial value int count = 0 here; // 1. Declare slot function (law of least privilege) private slots: void mySlot(); }; #endif // DIALOG_H
dialog.cpp
#include "dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent),count(0)// (2) Construct initialization list { // (3) Assign count = 0 in the constructor; resize(200, 200); btn = new QPushButton("0", this); btn->move(50, 50); // 3. Connect the signal slot connect(btn, SIGNAL(clicked()), this, SLOT(mySlot())); } // 2. Define the slot function void Dialog::mySlot() { // add count++; // int integer → QString string QString text = QString::number(count); btn->setText(text); } Dialog::~Dialog() { delete btn; }
Static local variable code example: not recommended
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QPushButton> class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); private: QPushButton* btn; // 1. Declare slot function (law of least privilege) private slots: void mySlot(); }; #endif // DIALOG_H
dialog.cpp
#include "dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent) { resize(200, 200); btn = new QPushButton("0", this); btn->move(50, 50); // 3. Connect the signal slot connect(btn, SIGNAL(clicked()), this, SLOT(mySlot())); } // 2. Define the slot function void Dialog::mySlot() { static int count = 0; // add count++; // int integer → QString string QString text = QString::number(count); btn->setText(text); } Dialog::~Dialog() { delete btn; }
Static local variables are not as easy to use as member variables
If there are multiple Dialog object windows, multiple windows use a static local variable, click one and all will change accordingly
Unless you want to make such effects, it is recommended to use member variables
In addition, the life cycle of static member variables is longer, and the use of member variables is more lightweight
operation result
signal slot parameter
Signal slot parameter passing is mainly used in the later stage when it is inconvenient to directly use variables to pass parameters. This is only for explanation and demonstration, not the optimal solution
[Example] Click the button, the number of clicks of the current button is displayed on the button
Idea: Different from the idea used by global variables, it is recommended to go back and compare the differences
code show as below:
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QPushButton> class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); private: QPushButton* btn; private slots: // Custom slot function 1 void mySlot(); // Slot function 2 connected with void valueSignal(int) void valueSlot(int); signals: // Signal functions that can take parameters // The signal function does not need to be defined, does not need to be called, and can be emitted directly void valueSignal(int); }; #endif // DIALOG_H
dialog.cpp
#include "dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent) { resize(300, 300); btn = new QPushButton("0", this); btn->move(100, 100); connect(btn, SIGNAL(clicked()), this, SLOT(mySlot())); connect(this, SIGNAL(valueSignal(int)), this, SLOT(valueSlot(int))); } void Dialog::mySlot() { // Count using static local variables static int count = 0; // Send a custom signal emit valueSignal(++count); } // Dummy arguments cannot be used here, and the parameter name must be written, otherwise the parameter value cannot be obtained void Dialog::valueSlot(int count) { // Get the passed parameters and set the display QString text = QString::number(count); btn->setText(text); } Dialog::~Dialog() { delete btn; }
The result of the operation is the same as above
Compared with global parameters, the efficiency is lower. If you can use parameter passing, do not use signal slots to pass parameters.
Signal slot passing parameters is a method for use when parameter passing is inconvenient
Signal slot transfer parameters are set for more complex long-distance communication
Long distance is not the actual distance, but there is no direct relationship between two objects in programming
If two objects in a class are within reach between them, it is not called long-distance
Notice:
- In theory, any number of parameters can be passed, but in practice 1-2 are mostly.
- The number of parameters of the signal function must be greater than or equal to the number of parameters of the slot function.
- Parameter types must match one by one
Correspondence between signal slots
There is a one-to-many and many-to-one relationship between signal slots
One-to-many refers to a signal that can connect to multiple slot functions
Many-to-one means that multiple signals can be connected to the same slot function
One-to-many situations can be optimized to one-to-one
[Example] One-to-many and optimized into a simplified version of one-to-one
Code example:
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QPushButton> #include <QDebug> class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); private: QPushButton* btn1; QPushButton* btn2; private slots: // two slot functions void mySlot1(); void mySlot2(); // Slot function connected with btn2 void mySlot(); }; #endif // DIALOG_H
dialog.cpp
#include "dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent) { resize(200, 200); btn1 = new QPushButton("one-to-many", this); btn2 = new QPushButton("Simplified version", this); btn1->move(100, 50); btn2->move(100, 100); // one-to-many connect(btn1, SIGNAL(clicked()), this, SLOT(mySlot1())); connect(btn1, SIGNAL(clicked()), this, SLOT(mySlot2())); // All one-to-many can be reduced to one-to-one signals and slots connect(btn2, SIGNAL(clicked()), this, SLOT(mySlot())); } void Dialog::mySlot1() { qDebug() << "1"; } void Dialog::mySlot2() { qDebug() << "2"; } void Dialog::mySlot() { // A slot function is a special kind of member function // can be called directly mySlot1(); mySlot2(); } Dialog::~Dialog() { delete btn1; delete btn2; }
operation result
Starting E:\QT\Tools\QtCreator\bin\build-qtday2_onetomuti-Desktop_Qt_5_2_1_MinGW_32bit-Debug\debug\qtday2_onetomuti.exe... 1 2 1 2 E:\QT\Tools\QtCreator\bin\build-qtday2_onetomuti-Desktop_Qt_5_2_1_MinGW_32bit-Debug\debug\qtday2_onetomuti.exe exited with code 0
Both Button one-to-many and Button simplified version can implement signal slots
[Example] many to one
Code example:
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QDebug> #include <QWidget> #include <QPushButton> #define QPushButton_STYTLE (QString("\ /*button normal state*/\ QPushButton\ {\ font-family:Microsoft Yahei;\ /*Font size is 20 points*/\ font-size:10pt;\ /*font color is white*/\ color:white;\ /*background color*/\ background-color:rgb(0 , 0 , 0);\ /*Border corner radius is 8 pixels*/\ border-radius:20px;\ }\ /*button hover state*/\ QPushButton:hover\ {\ /*background color*/\ background-color:rgb(0 , 0 , 0);\ }\ /*button pressed state*/\ QPushButton:pressed\ {\ color:black;\ /*background color*/\ background-color:rgb(255 , 255 , 255);\ /*The left padding is 3 pixels, so that the word moves 3 pixels to the right when pressed*/\ padding-left:3px;\ /*The upper padding is 3 pixels, so that the word moves down by 3 pixels when pressed*/\ padding-top:3px;\ }")) class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); private: QPushButton *btn; QPushButton *btn1; QPushButton *btn2; QPushButton *btn3; int count; private slots: void mySlot(); }; #endif // DIALOG_H
dialog.h
#include "dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent),count(0) { resize(640,480); btn=new QPushButton(NULL,this); btn->resize(640,480); btn1=new QPushButton("click",this); btn1->setStyleSheet(QPushButton_STYTLE); btn1->move(280,240); btn1->resize(100,50); btn2=new QPushButton("click",this); btn2->setStyleSheet(QPushButton_STYTLE); btn2->move(280,180); btn2->resize(100,50); btn3=new QPushButton("click",this); btn3->setStyleSheet(QPushButton_STYTLE); btn3->move(280,300); btn3->resize(100,50); connect(btn,SIGNAL(clicked()),this,SLOT(mySlot())); connect(btn1,SIGNAL(clicked()),this,SLOT(mySlot())); connect(btn2,SIGNAL(clicked()),this,SLOT(mySlot())); connect(btn3,SIGNAL(clicked()),this,SLOT(mySlot())); } void Dialog::mySlot(){ count++; qDebug()<<count; QString test=QString::number(count); btn1->setText(test); btn2->setText(test); btn3->setText(test); } Dialog::~Dialog() { delete btn; delete btn1; delete btn2; delete btn3; }
operation result
Starting E:\QT\Tools\QtCreator\bin\build-qtday2_onetomuti-Desktop_Qt_5_2_1_MinGW_32bit-Debug\debug\qtday2_onetomuti.exe... 1 2 3 4 E:\QT\Tools\QtCreator\bin\build-qtday2_onetomuti-Desktop_Qt_5_2_1_MinGW_32bit-Debug\debug\qtday2_onetomuti.exe exited with code 0
Summarize
there will be a period later