Signal and slot of QT core mechanism and Principle
Signal and slot
The signal and slot mechanism is one of the core mechanisms of QT. To master QT programming, you need to understand the signal and slot. Signals and slots are an advanced interface used for communication between objects. They are the core feature of QT and are also an important part of QT which is different from other similar tool kits.
In other GUI toolkit we know, Widgets all have a callback function to respond to the actions they trigger. This callback function is usually a pointer to a function. In QT, the above mechanism is replaced by signals and slots.
1.
Signal (signal)
When
When the object state changes, the signal is sent by an object (emit ). Only the class that defines this signal or its derived class can transmit this signal. When a signal is transmitted
Executed, just like a normal function call. The signal-slot mechanism is independent of any GUI event loop. The emission function (emit) returns only when all slots are correctly returned.
If multiple slots are associated with a signal, these slots will be executed one by one when the signal is sent, however, the execution sequence is uncertain, and we cannot specify the execution sequence.
The signal is declared in the header file, and the MOC tool will be careful not to define the signal in the implementation file. Qt uses the signals keyword to identify the signal declaration area and then declares its own signal. For example, several signals are defined below:
signals:
void yourSignal();
void yourSignal(int x);
In the preceding statement, signals is the key word of QT. The following line void yoursignal ();
Defines the signal yoursignal, which does not carry parameters; the following line void yoursignal (int x); defines
The signal yoursignal (int x), but it carries an integer parameter, which is similar to overload.
Note: the Declaration of signal and slot functions is generally located in the header file, and the q_object statement must be added at the beginning of the class declaration. This statement is indispensable and will tell the compiler to compile it.
You must first apply the MOC tool for extension. The keyword signals indicates the declaration of the subsequent start signal. Here, signals uses the form of plural instead of singular, and siganls does not
Attributes such as public, private, and protected are different from slots. In addition, the signals and slots keywords are defined by QT, not c ++.
Keyword.
Also, the declaration of signals is similar to the declaration of functions rather than variables. There must be a type on the left and parentheses on the right. If you want to pass parameters to the slot, specify the type of each formal parameter in brackets. Of course, the number of formal parameters can be more than one.
Formally speaking, the signal declaration is the same as the ordinary C ++ function, but the signal has no defined function implementation. In addition, the return types of signals are void, while the return values of C ++ functions can be of various types.
Note that the signal code is automatically generated by MOC, and MoC converts it into a standard C ++ statement. The C ++ Preprocessor considers itself to be a standard C ++ source file. Therefore, do not implement signal in your own C ++ file.
2.
Slot)
A slot is a common C ++ member function that can be called normally. The difference is that it can be associated with a signal. This slot is called when the signal associated with it is sent. Slot can have parameters, but slot parameters cannot have default values.
The slot has the same access permissions as common member functions. The access permission of the slot determines who can connect to it. Generally, slots are divided into three types: Public slots, private slots, and protected slots.
Public
Slots: The slots declared in this code segment means that any object can connect the signal to it. This is very useful for component programming: You have generated many objects and they do not know each other.
The signal is connected to the slot so that the information can be transmitted correctly, and it is like a train model on a railway track where a child is fond of playing. Open it and let it run.
Protected slots: The slots declared in this code segment means that the current class and its subclass can associate signals with it. These slots are only part of the implementation of the class, rather than its external interfaces.
Private slots: The slots declared in this code segment means that only the class itself can associate the signal with it. This means that these slots are very close to this class, and even its sub-classes do not have the trust of connection rights.
Generally, it is common to use public and private declaration slots. We recommend that you do not use the protected keyword to modify slot attributes. In addition, the slot can be declared as a virtual function.
The slot statement is also carried out in the header file. For example, the following statements describe several slots:
public slots:
void yourSlot();
void yourSlot(int x);
Note: The keyword slots indicates the declaration of the slot that begins later. Here slots also use the plural form.
3.
Correlation between signals and slots
The slot is almost the same as a common C ++ member function-it can be a virtual function; it can be overloaded; it can be a common, protected, or private function, it can also be directly called by other C ++ member functions;
Yes. Their parameters can be of any type. The only difference is that the slot can be connected with the signal. In this case, the slot is automatically called whenever the signal is sent.
The CONNECT () statement looks like the following:
connect(sender,SIGNAL(signal),receiver,SLOT(slot));
Here, sender and handler are pointers to qobject, while signal and slot are function names without parameters. In fact, the signal () macro and slot () will convert their parameters into corresponding strings.
So far, in the instances we have seen, we have connected different signals with different slots. However, there are other possibilities to consider.
(1) One signal can be connected to multiple slots
connect(slider,SIGNAL(valueChanged(int)),spinBox,SLOT(setValue(int)));
connect(slider,SIGNAL(valueChanged(int)),this,SLOT(updateStatusBarIndicator(int)));
When this signal is sent, these slots are called one by one in an uncertain order.
(2) Multiple signals can be connected to the same slot
connect()
This slot is called no matter which signal is sent.
(3) one signal can be connected to another signal.
connect(lineEdit,SIGNAL(textChanged(const Qstring &)),this,SIGNAL(updateRecord(const Qstring &)));
When the first signal is sent, the second signal is also sent. In addition, the connection between the signal and the slot are difficult to distinguish.
(4) The connection can be removed.
disconnect(lcd,SIGNAL(overflow()),this,SLOT(handleMathError()));
This is rarely used, because when you delete an object, QT automatically removes all connections related to this object.
To successfully connect a signal to a slot (or to another signal), the parameters must have the same sequence and type.
connect(ftp,SIGNAL(rawCommandReply(int,const QString &)),this,SLOT(processReply(int,const QString &)));
If the signal parameter is more than the Slot Parameter connected to it, the extra parameter will be ignored.
connect(ftp,SIGNAL(rawCommandReply(int,const Qstring &)),this,SLOT(checkErrorCode(int)));
In addition, if the parameter type does not match, or if the signal or slot does not exist, QT will issue a warning at runtime when the application is built in debug mode. Similarly, if the parameter name is included in the signal and slot names, QT will also issue a warning.
The signal and slot mechanisms are implemented in qobject and are not limited to graphic user interface programming. This mechanism can be used in any qobject subclass.
The macro signal () of QT must be used when the signal is specified, and the macro slot () must be used when the slot function is specified (). If the initiator and receiver belong to the same object, the receiver parameter can be omitted in the Connect call.
For example, the following two objects are defined: the label object and the scroll object of the scroll bar, And the valuechanged () signal is associated with the setnum () of the label object, in addition, the signal carries an integer parameter, so that the label always displays the value of the position of the scroll bar.
QLabel *label = new QLabel;
QScrollBar *scroll = new QScrollBar;
QObject::connect( scroll, SIGNAL(valueChanged(int)),
label, SLOT(setNum(int)) );
4.
Example of signal and slot connection
The following is an example of the qobject subclass:
class BankAccount : public QObject
{
Q_OBJECT
public:
BankAccount() { curBalance = 0; }
int balance() const { return curBalance; }
public slots:
void setBalance(int newBalance);
signals:
void balanceChanged(int newBalance);
private:
int currentBalance;
};
Similar to most C ++ classes, the bankaccount class has constructor, balance () "read" function, and setbalance ()
"Set" function. It also has a balancechanged () signal, which is sent when the account balance is changed. When a signal is sent, the slot connected to it is executed.
The Set function is declared in the public slot, so it is a slot. The slot can be called as a member function, just like any other function, or connected to a signal. The following is the implementation process of the setbalance () slot:
void BankAccount::setBalance(int newBalance)
{
if (newBalance != currentBalance)
{
currentBalance = newBalance;
emit balanceChanged(currentBalance);
}
}
Statement emit balancechanged (currentbalance); The balancechanged () signal is sent and the current new balance is used as its parameter.
Keyword emit is similar to "signals" and "slots", provided by QT, and converted from C ++ Preprocessor to Standard C ++ statement.
The following example shows how to connect two bankaccount objects:
BankAccount x, y;
connect(&x, SIGNAL(balanceChanged(int)), &y, SLOT(setBalance(int)));
x.setBalance(2450);
When the balance in X is set to 2450, the system sends a balancechanged () signal. Setbalance () in Y ()
After receiving this signal, the slot sets the balance in Y
2450. The signal of an object can be connected to multiple different slots, and multiple signals can also be connected to a slot of a specific object. Signals with the same parameter type and slots can be connected to each other. The number of Slot parameters can be less
The number of signal parameters. In this case, extra parameters are ignored.
5. Notes
The signal and slot mechanisms are flexible, but we must understand some limitations so that we can be specific in the actual use process to avoid some errors. The following describes the situation.
(1)
The signal and slot efficiency is very high, but compared with the real callback function, due to increased flexibility, there is still a loss in speed, of course, this loss is relatively small.
The i586-133's machine testing is 10 microseconds (running Linux), which shows that the simplicity and flexibility provided by this mechanism is worthwhile. However, if we want to pursue high efficiency, such as in real-time systems
To minimize this mechanism.
(2) The signal and slot mechanism are the same as the call of common functions. If improperly used, an endless loop may also occur during program execution. Therefore, when defining the slot function, you must avoid indirect infinite loops, that is, re-transmit the same signal received in the slot.
(3) If a signal is associated with multiple slots, when the signal is sent, the activation sequence of the slots involved will be random, we cannot specify this order.
(4) macro definition cannot be used in parameters of signal and slot.
The struct constructor cannot be used in the signals or slots declaration area.
The evaluate function pointer cannot be used as a signal or slot parameter.
The swap signal and slot cannot have default parameters.
The middleware signal and slot cannot carry template parameters.