上一节我们详细分析了connect()
函数。使用connect()
可以让我们连接系统提供的信号和槽。但是,Qt 的信号槽机制并不仅仅是使用系统提供的那部分,还会允许我们自己设计自己的信号和槽。这也是 Qt 框架的设计思路之一,用于我们设计解耦的程序。本节将讲解如何在自己的程序中自定义信号槽。
信号槽不是 GUI 模块提供的,而是 Qt 核心特性之一。因此,我们可以在普通的控制台程序使用信号槽。
经典的观察者模式在讲解举例的时候通常会举报纸和订阅者的例子。有一个报纸类Newspaper
,有一个订阅者类Subscriber
。Subscriber
可以订阅Newspaper
。这样,当Newspaper
有了新的内容的时候,Subscriber
可以立即得到通知。在这个例子中,观察者是Subscriber
,被观察者是Newspaper
。在经典的实现代码中,观察者会将自身注册到被观察者的一个容器中(比如subscriber.registerTo(newspaper)
)。被观察者发生了任何变化的时候,会主动遍历这个容器,依次通知各个观察者(newspaper.notifyAllSubscribers()
)。
下面我们看看使用 Qt 的信号槽,如何实现上述观察者模式。注意,这里我们仅仅是使用这个案例,我们的代码并不是去实现一个经典的观察者模式。也就是说,我们使用 Qt 的信号槽机制来获得同样的效果。
newspaper.h
#ifndef NEWSPAPER_H
#define NEWSPAPER_H
#include<QObject>
class Newspaper: public QObject
{
Q_OBJECT
public:
Newspaper(const QString &name):m_name(name)
{
}
void send()
{
emit newpaper(m_name);
}
signals:
void newpaper(QString &name);
private:
QString m_name;
};
#endif // NEWSPAPER_H
//reader.h
#ifndef READER_H
#define READER_H
#include <QObject>
#include <QDebug>
class Reader : public QObject
{
Q_OBJECT
public:
Reader() {}
void receive(const QString & name)
{
qDebug() << "get Newspaper: " << name;
}
};
#endif // READER_H
//main.c
#include "mainwindow.h"
#include <QApplication>
#include<QPushButton>
#include<newspaper.h>
#include<reader.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Newspaper newspaper("China Daily");
Reader reader;
QObject::connect(&newspaper,&Newspaper::newpaper,&reader,&Reader::receive);
newspaper.send();
return a.exec();
}
运行结果:
参考链接:https://www.devbean.net/2012/08/qt-study-road-2-custom-signal-slot/