【Qt开发】Qt信号与槽 示例

来源:互联网 发布:fifaonline3数据库 编辑:程序博客网 时间:2024/05/16 17:15

假设基于这样的一个情况:

在某一个程序里有两个主要的两个逻辑功能部分---UI交互的功能块和用于网络通信的网络功能块。当网络中有新的消息到达时,网络功能块需要通知UI刷新信息的显示;当用户输入新的操作命令或信息时,UI功能块将通过调用网络程序来进行数据的传送。

在非Qt程序中,我们一般是通过函数的回调或事件监听机制来实现这样的程序。打个比方,假设有类A和类B,类A对象中存有类B对象的指针,同时将自身的对象指针传到类B中去,这样便可以实现了函数的回调;A对象可以调用B的公有方法,同时B也可以根据具体情况来回调A的公有方法。

这种方式类似于通用设计模式中的观察者模式,只是观察者模式提供了更抽象的封装而已,比如对象之间互传的指针都是基于动态绑定的对象指针。

回到正题,在Qt程序中更偏向于使用信号与槽的机制来解决这样的问题。当然信号与槽机制的作用远远不止这些。

基于这种机制,不同对象之间可以发送信号,也可以接受信号,接收信号的方法称为槽。概括来说它有几个特性:(1)相对于普通的回调机制,它没有复杂的指针对象,只是指定了发送信号和接受信号的对象。(2)一个槽可以接收多个对象发出来的信号,一个信号也可以与多个槽连接。(3)在跨线程或进程的函数调用中,信号与槽的机制显得更为安全和灵活,而省去了一些非安全的显式指针调用。

下面是一个简单的例子,演示信号与槽的工作原理。

(1)定义信号

#include <QObject>class A : public QObject{    Q_OBJECTpublic:    A(QObject* parent = 0);    signals:    void message_arrive(QString msg);};

#include "a.h"A::A(QObject* parent) : QObject(parent){}

作为signal与slot中的一个参与者对象,它必须是QObject对象,也就是它必须要从QObject中派生而来。同时也要求在类声明中添加宏Q_OBJECT的声明,宏Q_OBJECT的作用是默认实现了Qt对象模型所需的几个关键函数。

关于信号,有几个特点:(1)信号的定义关键字是signals,不需要添加访问级别的关键字修饰,因信号总是被默认为public的,以便在不同类之间通信。(2)信号总是只有声明,而没有定义体的,这就好比C++的纯虚函数一样。(3)信号和槽之间传递的参数必须对应。(4)信号的返回类型总是void,即没有返回值。

(2)定义槽

#include <QObject>class B : public QObject{    Q_OBJECTpublic:    B(QObject* parent = 0);    public slots:    void reflash_text(QString msg);};
#include "b.h"B::B(QObject* parent) : QObject(parent){}void B::reflash_text(QString msg){    // TODO:接收信号并处理参数}

槽的访问级别可以设置成public, proteced, private,这个根据具体情况而定;同时需要实现相应的函数体。当然,信号与

槽也可以同时定义在同一个对象中。

(3)连接信号与槽

方法调用:QObject::connect(const QObject *asender, const char *asignal,const QObject *areceive, const char *asignal, Qt::ConnectionType atype)。最后一个参数是可选的,代表采取的连接类型(连接类型会设计到安全性问题,比如不同线程间的信号与槽连接类型普遍采取QueuedConnection等)。

对于上面的示例,则可以这样连接:

QObject::connect(a, SIGNAL(message_arrive(QString)), this, SLOT(reflash_text(QString)));

其中a为类A的一个对象的指针; this指向类B的一个对象本身,也就是说这个函数connect()在B中调用。




原创粉丝点击