Qt学习2

来源:互联网 发布:微商授权系统源码 编辑:程序博客网 时间:2024/04/29 23:16

摘自:http://www.devbean.net/2012/08/qt-study-road-2-catelog/

经典的观察者模式在讲解举例的时候通常会举报纸和订阅者的例子。有一个报纸类Newspaper,有一个订阅者类SubscriberSubscriber可以订阅Newspaper。这样,当Newspaper有了新的内容的时候,Subscriber可以立即得到通知。在这个例子中,观察者是Subscriber,被观察者是Newspaper。在经典的实现代码中,观察者会将自身注册到被观察者的一个容器中(比如subscriber.registerTo(newspaper))。被观察者发生了任何变化的时候,会主动遍历这个容器,依次通知各个观察者(newspaper.notifyAllSubscribers())。

下面我们看看使用 Qt 的信号槽,如何实现上述观察者模式。注意,这里我们仅仅是使用这个案例,我们的代码并不是去实现一个经典的观察者模式。也就是说,我们使用 Qt 的信号槽机制来获得同样的效果。

#ifndef NEWSPAPER_H#define NEWSPAPER_H// 首先看Newspaper这个类。这个类继承了QObject类。// 只有继承了QObject类的类,才具有信号槽的能力。// 所以,为了使用信号槽,必须继承QObject。#include <qobject.h>class Newspaper :public QObject{// 凡是QObject类(不管是直接子类还是间接子类),// 都应该在第一行代码写上Q_OBJECT。// 不管是不是使用信号槽,都应该添加这个宏。Q_OBJECTpublic:Newspaper(const QString &name) :m_name(name){}void send(){emit newPaper(m_name);}/* * emit 是 Qt 对 C++ 的扩展,是一个关键字(其实也是一个宏)。emit 的含义是发出,也就是发出newPaper()信号。 * 感兴趣的接收者会关注这个信号,可能还需要知道是哪份报纸发出的信号?所以,我们将实际的报纸名字m_name当做参数传给这个信号。 * 当接收者连接这个信号时,就可以通过槽函数获得实际值。这样就完成了数据从发出者到接收者的一个转移。 */signals:void newPaper(const QString &name);/* * Newspaper类的 public 和 private 代码块都比较简单,只不过它新加了一个 signals。 * signals 块所列出的,就是该类的信号。信号就是一个个的函数名,返回值是 void *(因为无法获得信号的返回值,所以也就无需返回任何值),参数是该类需要让外界知道的数据。 * 信号作为函数名,不需要在 cpp 函数中添加任何实现(我们曾经说过,Qt 程序能够使用普通的 make 进行编译。 * 没有实现的函数名怎么会通过编译?原因还是在 moc,moc 会帮我们实现信号函数所需要的函数体, * 所以说,moc 并不是单纯的将 Q_OBJECT 展开,而是做了很多额外的操作) */private:QString m_name;};#endif

#ifndef READER_H#define READER_H#include <qobject.h>#include <qdebug.h>class Reader :public QObject{Q_OBJECTpublic:Reader(){}// Qt 5 中,任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数。// 与信号函数不同,槽函数必须自己完成实现代码。void receiveNewspaper(const QString &name){qDebug() << "Receives Newspaper: " << name;}};#endif

#include <QtWidgets/QApplication>#include <qlabel.h>#include "Newspaper.h"#include "Reader.h"int main(int argc, char *argv[]){QApplication a(argc, argv);Newspaper newspaper("Newspaper A");Reader reader;         //connect(sender, signal, receiver, slot);        QObject::connect(&newspaper, &Newspaper::newPaper,&reader, &Reader::receiveNewspaper);newspaper.send();/* * main()函数中,我们首先创建了Newspaper和Reader两个对象,然后使用QObject::connect()函数。 * 这个函数我们上一节已经详细介绍过,这里应该能够看出这个连接的含义。然后我们调用Newspaper的send()函数。 * 这个函数只有一个语句:发出信号。由于我们的连接,当这个信号发出时,自动调用 reader 的槽函数,打印出语句。 */return a.exec();}
QT4中应该为QObject::connect(&newspaper, SIGNAL(newPaper(QString)),
                                                        &reader,    SLOT(receiveNewspaper(QString)));

第二、第四个参数需要使用SIGNALSLOT这两个宏转换成字符串(具体事宜我们在上一节介绍过)。注意SIGNALSLOT的宏参数并不是取函数指针,而是除去返回值的函数声明,并且 const 这种参数修饰符是忽略不计的。

0 0
原创粉丝点击