Inside Qt Series (十):connect,幕后的故事
来源:互联网 发布:北京域名备案查询 编辑:程序博客网 时间:2024/04/29 04:20
http://www.qkevin.com/archives/85
作者:Q-Kevin @ http://www.qkevin.com
我们都知道,把一个signal和slot连接起来,需要使用QObject类的connect方法,它的作用就是把一个object的signal和另外一个object的slot连接起来,以达到对象间通讯的目的。
connect 在幕后到底都做了些什么事情?为什么emit一个signal后,相应的slot都会被调用?好了,让我们来逐一解开其中的谜团。
SIGNAL 和 SLOT 宏定义
我们在调用connect方法的时候,一般都会这样写:
obj.connect(&obj, SIGNAL(destroyed()), &app, SLOT(aboutQt()));
我们看到,在这里signal和slot的名字都被包含在了两个大写的SIGNAL和SLOT中,这两个是什么呢?原来SIGNAL 和 SLOT 是Qt定义的两个宏。好了,让我们先来看看这两个宏都做了写什么事情:
这里是这两个宏的定义:
# define SLOT(a) "1"#a
# define SIGNAL(a) "2"#a
原来Qt把signal和slot都转化成了字符串,并且还在这个字符串的前面加上了附加的符号,signal前面加了’2’,slot前面加了’1’。也就是说,我们前面写了下面的connect调用,在经过moc编译器转换之后,就便成了:
obj.connect(&obj, "2destroyed()", &app, "1aboutQt()”));
当connect函数被调用了之后,都会去检查这两个参数是否是使用这两个宏正确的转换而来的,它检查的根据就是这两个前置数字,是否等于1或者是2,如果不是,connect函数当然就会失败啦!
然后,会去检查发送signal的对象是否有这个signal,方法就是查找这个对象的class所对应的staticMetaObject对象中所包含的d.stringdata所指向的字符串中是否包含这个signal的名字,在这个检查过程中,就会用到d.data所指向的那一串整数,通过这些整数值来计算每一个具体字符串的起始地址。同理,还会使用同样的方法去检查slot,看响应这个signal的对象是否包含有相应的slot。这两个检查的任何一个如果失败的话,connect函数就失败了,返回false.
前面的步骤都是在做一些必要的检查工作,下一步,就是要把发送signal的对象和响应signal的对象关联起来。在QObject的私有数据类QObjectPrivate中,有下面这些数据结构来保存这些信息:
class QObjectPrivate : public QObjectData
{
struct Connection
{
QObject *receiver;
int method;
uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
QBasicAtomicPointer<int> argumentTypes;
};
typedef QList<Connection> ConnectionList;
QObjectConnectionListVector *connectionLists;
struct Sender
{
QObject *sender;
int signal;
int ref;
};
QList<Sender> senders;
}
在发送signal的对象中,每一个signal和slot的connection,都会创建一个QObjectPrivate::Connection对象,并且把这个对象保存到connectionList这个Vector里面去。
在响应signal的对象中,同样,也是每一个signal和slot的connection,都会一个创建一个Sender对象,并且把这个对象附加在Senders这个列表中。
以上就是connect的过程,其中,创建QObjectPrivate::Connection对象和Sender对象的过程有一点点复杂,需要仔细思考才可以,有兴趣的朋友可以去读一下源代码。
======================================================================
声明:
《Inside Qt Series》专栏文章是(http://www.qkevin.com)原创技术文章。
本系列专栏文章可随意转载,但必须保留本段声明和每一篇文章的原始地址。
作者保留版权,未经作者同意,不得用于任何商业用途
《Inside Qt Series》专栏文章总索引: http://www.qkevin.com/qt
本文原始地址:http://www.qkevin.com/archives/85
- Inside QT Series (十):connect,幕后的故事
- Inside Qt Series (十):connect,幕后的故事
- Inside Qt Series (十):connect,幕后的故事
- Inside Qt Series (十):connect,幕后的故事
- Inside Qt Series (十):connect,幕后的故事
- Inside Qt Series (十):connect,幕后的故事
- Inside Qt Series (十一):emit,幕后的故事
- Inside Qt Series (十一):emit,幕后的故事
- Inside Qt Series (十一):emit,幕后的故事
- Inside Qt Series (十一):emit,幕后的故事
- Inside Qt Series (十一):emit,幕后的故事
- Inside Qt Series: Preface
- Inside Qt Series
- Inside Qt Series
- Inside QT Series 序
- Inside Qt Series (十二):Qt对象之间的父子关系
- Inside Qt Series (十二):Qt对象之间的父子关系
- Inside Qt Series (十二):Qt对象之间的父子关系
- 中缀到后缀的转换
- ant安装配置使用详解
- 非常简单的兼容多浏览器Javascript实现分页功能
- 网站常用模块
- ajax进度条 异步下载进度条
- Inside Qt Series (十):connect,幕后的故事
- Nagios中的check_oracle的简单使用
- POI 读取EXcel
- make 报错 make e=234
- 未加载ntdll.dll符号导致调用栈信息丢失
- Android开发环境搭建
- 让我们挖吧——Logminer(1)Logminer简介
- 不同IE下的css写法
- Pintics创始人创立ShopInterest: Pinterest购物新体验