一、QT5信号槽的深入理解和用户自定义信号槽
上一篇讲了信号槽的机制,现在我们看看如何建立自己QObject,以及QObject中的信号函数。
示例代码参照:https://www.devbean.net/2012/08/qt-study-road-2-custom-signal-slot/
#include <QObject>
////////// newspaper.h
class Newspaper : public QObject
{
Q_OBJECT //凡是QObject类(不管是直接子类还是间接子类),第一行代码必须加Q_OBJECT
public:
Newspaper(const QString & name) :
m_name(name)
{
}
void send()
{
emit newPaper(m_name);
}
signals:
void newPaper(const QString &name);
private:
QString m_name;
};
////////// reader.h
#include <QObject>
#include <QDebug>
class Reader : public QObject
{
Q_OBJECT
public:
Reader() {}
void receiveNewspaper(const QString & name)
{
qDebug() << "Receives Newspaper: " << name;
}
};
////////// main.cpp
#include <QCoreApplication>
#include "newspaper.h"
#include "reader.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Newspaper newspaper("Newspaper A");
Reader reader;
QObject::connect(&newspaper, &Newspaper::newPaper,
&reader, &Reader::receiveNewspaper);
newspaper.send();
return app.exec();
}
1)有关QObject的标准格式第一行的Q_OBJECT
这是一个宏定义,在编译器编译之前进行展开。这个宏由moc(一种在C++预处理器之前进行预处理的预处理器)进行展开,具体步骤包括:
1、展开宏定义内容
2、标记当前Q_OBJEECT宏所在的头文件,并生成moc_为前缀的文件
2)Newspaper类解析:
send()函数:发出信号
emit:前面说的Q_OBJECT的宏,含义为发出,也就是发出newPaper()信号,接收方如果想要接收,就能接收到newPaper()中的name信号。
newPaper():信号名字,实际为函数,在signals:中进行声明(但未实现)
signals:signals块中列出了所有信号,即一个个的函数名,返回值:void,参数:该类要让外界知道的数据。之所以在该QObject内没有实现的主体只有声明,是因为前面提到的moc_会根据Q_OBJECT的展开,在预编译时候帮我们实现。
3)Reader类和main()函数的解析:
1、Reader(QObject)类中的任何成员函数,静态函数,成员函数,lambda表达式都可以作为槽函数(前提为类外可以访问,所以声明为public)
2、main():
a、创建了我们定义的两个类的对象
b、调用connect()函数,建立了连接
c、命令newspaper类对象发出信号(调用send()函数)
d、我们发现此时reader自动打印出了内容,实现了槽函数的接收信号功能