QObject中主要的内容是关于信号与槽的管理方式,上一节已做了简单说明,本篇主要看下剩余的部分;
剩余的部分主要是关于对象回收机制、事件处理等内容;
1、QObject的Event事件
通过以上代码可知,QObject中主要有定时器事件,常用的定时器有QTimer,QTime等,后续会着重讲解其使用;timerEvent为虚函数,子类可以实现自定义的函数处理;
ChildAdded、ChildPolished、ChildRemoved等事件是在其更改其parent对象时,会触发此事件;
DeferredDelete事件:当准备删除此对象时触发;
MetaCall事件:当信号和槽的链接方式为队列时,最终会定位到此事件中
ThreadChange事件:更改为不同线程时触发;
User事件:为自定义事件,如果要捕获自定义事件,可以实现customEvent函数;
EventFilter事件其在QObject实现方式为空,后续会结合QCoreApplication来讲解Qt的事件系统
2、QObject对象管理既对象回收机制:
a、添加子对象到children列表中
首先了解下更改QObject对象的parent时,其执行的操作;
如果原parent对象不为空,则判断其是否正在被parent移除,如果已经执行deleteChildren函数则不需要再次在parent中移除;否则在parent的children链表中移除此对象,并发送ChildRemoved事件;
判断新的parent对象和当前对象是否为同一线程,如果不在同一个线程在抛出警告信息,并返回(如果不在同一个线程,则QObject对象内存无法自动被回收,需要手动删除);
将当前对象添加到新的parent对象的children链表中,并发送ChildAdded事件;
最后判断是否需要执行parentChaned函数;parentChanged函数为钩子函数;
b、删除子对象
当QObject对象被删除时,其对应的源码为(主要在析构函数中):
首先删除其子对象,既移除children链表中的对象;如果父对象不为空,将父对象设为空;
首先检测isDeletingChildren是否为true,如果为true,则触发断言;防止子对象被多次删除;
遍历children列表,将currentChildBeingDeleted赋值,更改children[i]为空,删除currentChildBeingDeleted对象;最后将children链表清空,更改对象的标志位;
注意:此地方先调用children[i]取出带删除的对象,然后将children[i]赋值为0,再删除此在对象;这样做应该是防止待删除对象执行其析构函数时消耗时间太长,而此时又执行了setParent方法时会引起异常(删除的对象又再次被添加到其他对象的children列表中,可以结合setParent方法理解)。
c、查找子对象
查找对象一般又2种方式,一种是查找一个对象,一种是查找所有相符的对象列表
查找相符合的一个对象
首先移除T对象的const、volatile、*等关键字,提取对象的原始类型;然后调用qt_qFindChild_helper函数。
遍历children列表,查找子对象中和T对象有继承关系的对象,且name为空或者和objectName相匹配时,既返回当前对象;如果再当前children列表中没有找到,且option为递归查找,则在子对象中查找。
qt_qFindChildren_helper函数
遍历children列表,查找子对象中是否和当前对象相匹配,如果相符,则添加到list列表中;
3、QTimer相关事件处理
启动定时器,主要调用eventDispatcher对象,注册一个定时器事件,并保存对应的定时器id到runningTimers中;
停止定时器,主要是调用事件分发器的unregisterTimer函数,并在runningTimers中移除对应的定时器;
后续分析QEventDispatcher函数时,会具体查看registerTimer及unRegisterTimer函数,猜测是调用windows及unix系统的api实现定时器事件的分发;
4、moveToThread函数
moveToThread函数主要有:1、遍历所有子对象并发送线程改变事件;2、将当前postEventList中待分发的事件转移到新的线程中;3、更改当前信号槽列表,将其存储的threadData信息调整为目标threadData;主要在setThreadData_helper中实现如下:
上图1:转移event事件到新的线程中
上图2:如果作为信号发送者,清空所有的信号接收者
上图3:如果作为信号接收者,调整发送信号对象中存储的线程信息(将threadData信息更改为目标线程信息)
最后循环遍历所有的子对象,并调整线程信息;