在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是槽函数。
当信号发送以后,槽函数就会被自动调用。