【QT】2. 信号/槽之概述

[b]一、对象之间的通讯问题[/b]

信号/槽机制是QT的核心机制,信号/槽是一种高级接口,应用于对象之间的通信,它是QT的核心特性,也是QT区别于其它工具包的重要地方。

和QT的信号/槽十分类似的概念是C#中的“委托”(delegate),当然后期发展出来的“委托”,在Microsoft的不懈努力下,更灵活也更容易使用些。

信号/槽或者委托,都是为了解决某些特定场景所设计的:即程序中有某些不可预测的部分,因而无法写死在当前方法中,需要“委托”其他的对象方法加以处理。这样的场景在GUI编程中十分普遍。

信号/槽是QT自行定义的一种通信机制,它独立于标准的C/C++语言,因此要正确的处理信号/槽,必须借助一个称为moc(Meta Object Compiler)的QT工具,该工具是一个C++预处理程序,它为高层次的事件处理自动生成所需要的附加代码。

[b]二、信号[/b]

所有从QObject或其子类(例如Qwidget)派生的类都能够包含信号和槽。


/*-----------------------------------------*/
/* informer.h for QT Signal/SLot */
/*-----------------------------------------*/
#pragma once
#include "qobject.h"

class Informer:public QObject
{
Q_OBJECT;
public:
void notify()
{
for(int i=0;i<=10;i++)
{
emit send(i);
}
};

signals:
void send(int status);

};


当对象改变其状态时,信号就由该对象发射(emit)出去,这就是对象所要做的全部事情,它不知道另一端是谁在接收这个信号。

当一个信号被发射时,与其相关联的槽将被立刻执行,就象一个正常的函数调用一样。只有当所有的槽返回以后发射函数(emit)才返回。 如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地 执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪个后执行。

[b]三、槽[/b]

槽用于接收信号,但它们是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接。而且,对象并不了解具体的通信机制。

/*-----------------------------------------*/
/* receiver.h for QT Signal/SLot */
/*-----------------------------------------*/
#pragma once
#include "qobject.h"

class Receiver:public QObject
{
Q_OBJECT;
private:
int total;
public:
Receiver(){this->total=0;};
public slots:
void count(int i)
{
printf("Counting: %d+%d=%d\n",this->total,i,this->total+i);
this->total=this->total+i;
};

};


槽是普通的成员函数,因此与其它的函数一样,它们也有存取权限。槽的存取权限决定了谁能够与其相关联。同普通的C++成员函数一样,槽函数也分为三种类型,即public slots、private slots和protected slots。
[list]
[*]public slots:在这个区内声明的槽意味着任何对象都可将信号与之相连接。这对于组件编程非常有用,你可以创建彼此互不了解的对象,将它们的信号与槽进行连接以便信息能够正确的传递。
[*]protected slots:在这个区内声明的槽意味着当前类及其子类可以将信号与之相连接。这适用于那些槽,它们是类实现的一部分,但是其界面接口却面向外部。
[*]private slots:在这个区内声明的槽意味着只有类自己可以将信号与之相连接。这适用于联系非常紧密的类。
[/list]

槽也能够声明为虚函数。
[b]
四、关联[/b]

通过调用QObject对象的connect函数可以将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用。


/*-----------------------------------------*/
/* main.cpp for QT Signal/SLot */
/*-----------------------------------------*/
#pragma once
#include "qobject.h"
#include "informer.h"
#include "receiver.h"

int main(int argc, char* argv[])
{
Informer *s=new Informer();
Receiver *r1=new Receiver();
QObject::connect(s,SIGNAL(send(int)),r1,SLOT(count(int)));
s->notify();
delete s,r1;
return 0;
}


在上面的例子中:Informer的通知事件产生的信号send()和Receiver的count函数相关联。当指定信号signal时必须使用QT的宏SIGNAL(),当指定槽函数时必须使用宏SLOT()。如果发射者与接收者属于同一个对象的话,那么在connect调用中接收者参数可以省略。

[b]五、信号/槽的一些限制[/b]
1. 在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发射所接收到的同样信号。
2. 宏定义不能用在signal和slot的参数中。
3. 构造函数不能用在signals或者slots声明区域内。
4. 函数指针不能作为信号或槽的参数,如需使用,必须用typedef.
5. 信号与槽不能有缺省参数
6. 信号与槽也不能携带模板类参数,如需使用,必须用typedef.
7. 嵌套的类不能位于信号或槽区域内,也不能有信号或者槽。
8. 友元声明不能位于信号或者槽声明区内.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值