【Qt开发】Qt信号与槽 示例
假设基于这样的一个情况:
在某一个程序里有两个主要的两个逻辑功能部分---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_OBJECT
public:
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_OBJECT
public:
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中调用。
上一篇: 【unity3d】碰撞器与触发器
下一篇: Unity中碰撞与触发的理解与效果实现