自定义信号与槽

来源:互联网 发布:凤台县残疾人数据 编辑:程序博客网 时间:2024/06/12 09:09

    使用 connect()可以让我们连接系统提供的信号和槽。但是, Qt 的信号槽机制并不仅仅是使用系统提供的那部分,还会允许我们自己设计自己的信号和槽。这也是 Qt 框架的设计思路之一,用于我们设计解耦的程序。本节将讲解如何在自己的程序中自定义信号槽。信号槽不是 GUI 模块提供的,而是 Qt 核心特性之一。因此,我们可以在普通的控制台程序使用信号槽。经典的观察者模式在讲解举例的时候通常会举报纸和订阅者的例子。有一个报纸类Newspaper,有一个订阅者类 Subscriber。 Subscriber 可以订阅 Newspaper。这样,当Newspaper 有了新的内容的时候, Subscriber 可以立即得到通知。在这个例子中,观察者是 Subscriber,被观察者是 Newspaper。在经典的实现代码中,观察者会将自身注册到被观察者的一个容器中(比如 subscriber.registerTo(newspaper))。被观察者发生了任何变化的时候,会主动遍历这个容器,依次通知各个观察者(newspaper.notifyAllSubscribers())。下面我们看看使用 Qt 的信号槽,如何实现上述观察者模式。注意,这里我们仅仅是使用这个案例,我们的代码并不是去实现一个经典的观察者模式。也就是说,我们使用 Qt 的信号槽机制来获得同样的效果。

#ifndef NEWSPAPER_H#define NEWSPAPER_H#include <QObject>/**只有继承了 QObject 类的类,才具有信号槽的能力。所以,为了使用信号槽,*必须继承 QObject。凡是 QObject 类(不管是直接子类还是间接子类),*都应该在第一行代码写上 Q_OBJECT。不管是不是使用信号槽,都应该添加这个宏。*这个宏的展开将为我们的类提供信号槽机制、国际化机制以及 Qt 提供的不基于*C++ RTTI 的反射能力。*/class NewSpaper:public QObject{Q_OBJECTprivate:QString m_name;public:NewSpaper(const QString & name):m_name(name){}void send(){/** emit 是 Qt对 C++ 的扩展, 是一个关键字 (其实也是一个宏)。emit 的含义是发出,* 也就是发出 newPaper()信号。*/emit newPaper(m_name);}/** signals块所列出的,就是该类的信号。信号就是一个个的函数名,* 返回值是 void(因为无法获得信号的返回值,所以也就无需返回任何值),* 参数是该类需要让外界知道的数据。信号作为函数名,不需要在 cpp 函数中添加任何实现.*/signals:void newPaper(const QString & name);};#endif // NEWSPAPER_H
#ifndef RENDER_H#define RENDER_H#include <QObject>#include <QDebug>class Render:public QObject{Q_OBJECTpublic:Render(){}void receiveNewspaper(const QString & name){qDebug()<<"接收者:"<<name;}};#endif // RENDER_H
#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>class MainWindow : public QMainWindow{Q_OBJECTpublic:MainWindow(QWidget *parent = 0);~MainWindow();};#endif // MAINWINDOW_H
#include "mainwindow.h"#include <QApplication>#include "newspaper.h"#include "render.h"/** 自定义信号槽需要注意的事项:* 发送者和接收者都需要是 QObject 的子类 (当然, 槽函数是全局函数、 Lambda 表达式等无需接收者的时候除外);* 使用 signals 标记信号函数,信号是一个函数声明,返回 void,不需要实现函数代码;* 槽函数是普通的成员函数,会受到 public、 private、 protected 的影响;* 使用 emit 在恰当的位置发送信号;* 使用 QObject::connect() 函数连接信号和槽*/int main(int argc, char *argv[]){NewSpaper np("发送者");Render rd;QObject::connect(&np,&NewSpaper::newPaper,&rd,&Render::receiveNewspaper);/** 调用 Newspaper 的 send() 函数。这个函数只有一个语句:发出信号。* 由于我们的连接,当这个信号发出时,自动调用 reader 的槽函数,打印出语句。*/np.send();return 0;}

0 0
原创粉丝点击