在Qt框架下,使用信號槽機制來完成事件處理。
信號就是發生的事件,槽就是處理事件的函數。這兩者不在一起,不像MFC的消息循環機制。它們是鬆散的耦合。要想將它們連接起來,那麼必須使用connect函數來連接它們。例如,當我想實現,點擊關閉按鈕就會關閉當前窗口的操作。那麼我就需要使用connect函數來連接“點擊”這個信號函數和“關閉”這個槽函數。
下面是我的代碼:
#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H
#include <QPushButton>
#include<QString>
class MyPushButton : public QPushButton
{
Q_OBJECT
public:
explicit MyPushButton(const int& x,const int& y,const QString& str,QWidget *parent = nullptr);
signals:
};
MyPushButton::MyPushButton(const int& x, const int& y,const QString& str,QWidget *parent) :QPushButton(parent)
{
this->setText(str);
this->move(x,y);
this->resize(100,50);
}
#endif // MYPUSHBUTTON_H
#include "widget.h"
#include"mypushbutton.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
QString str = "關閉";
MyPushButton button(300,200,str);
button.setParent(&w);
//連接信號槽
QObject::connect(&button,&MyPushButton::clicked,&QApplication::quit);
button.show();
w.show();
return a.exec();
}
這段代碼的核心在於就在於QObject::connect()函數的使用。只有在Widget類中寫了QObject,我們才能使用信號槽機制。因此,connect理所當然的就是QObject的函數成員。我們可以在幫助文檔中看到connect函數有6個重載函數。其中5個都是靜態成員函數,剩下的一個是普通成員函數。下面是這個普通connect函數的原型:
QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type = Qt::AutoConnection) const
這個普通成員函數需要使用一個QObject才能調用,但是我們確實沒有必要創建一個QObject對象,所以一般都是使用重載的5個靜態成員函數。
static QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
static QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection)
static QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection)
static QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
static QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)
仔細觀察這些connect函數,可以看出,發送者和接收者都是QObject指針類型(也就是說它們可以是QObject對象或者是QObject的派生類對象)。連接類型有一個默認值Qt::AutoConnection。信號和槽可以是const char*類型的,也可以是const QMetaMethod &類型,還可以是成員函數指針(PointerToMemberFunction),還可以是Functor類型,這個類型可以是能連接到信號的任意函數或者仿函數,lambda表達式。
注意:Qt::UniqueConnections do not work for lambdas, non-member functions and functors; they only apply to connecting to member functions.
很明顯,我的代碼中使用的是靜態函數中的第四個。
QObject::connect(&button,&MyPushButton::clicked,&QApplication::quit);
button是信號發送者,clicked是信號,quit是槽函數。
當我們點擊按鈕,發送信號,那麼槽函數quit就會被調用,從而程序退出。
lambda表達式請看這裏:https://blog.csdn.net/zy010101/article/details/73613664
信號槽要求信號和槽的參數一致。如果不一致,但是槽函數的參數可以比信號的少,即便如此,槽函數存在的那些參數的順序也必須和信號的前面幾個參數一致。因爲,你可以在槽函數中選擇忽略信號傳來的數據,但是不能說信號根本沒有這個參數,你就要在槽函數中使用。
我們一般使用的connect函數形式如下:
connect(sender, signal, receiver, slot);
sender是信號發送者,signal是信號,receiver是信號接收者,slot是槽函數。
當信號發送以後,槽函數就會被自動調用。