Qt 踩坑记录
吃一堑长一智
-
事件过滤器处理函数中添加事件过滤器
-
场景
- 假设有A、B、C三个类,它们都是QObject的子类
- 实例
A1安装了实例C1作为事件过滤器 - QApplication发送了一个事件
e给A1 C1捕捉到这个事件并对其进行处理,在处理的过程中创建了一个或多个B的实例,创建完后立刻给A1安装这些B的实例作为事件过滤器
-
后果
C1的eventFilter函数处理完本次的事件e后,控制流又会莫名其妙进入C1的eventFilter函数中,它又要处理一次事件e,处理完后控制流又进入C1的eventFilter函数,成为一个死循环永远出不去
-
原因
- 每个QObject将它的事件过滤器存在私有的数据结构中,其
d_ptr中的extraData的eventFilters就是存放它事件过滤器的列表 - QCoreApplication在执行
notify后,会调用QCoreApplicationPrivate::sendThroughObjectEventFilters函数,然后从头开始遍历事件接收者的这个eventFilters列表,一个个调用它们的eventFilter函数,如果其中有一个返回了true,那么就算拦截成功,事件将不会进一步传播 - 对一个QObject的实例执行
installEventFilter是将新的事件过滤器实例加入到这个列表的头部,所以这就是后装的事件过滤器优先过滤事件的原因 - 所以答案已经很明确了,
C1在处理事件e的时候,就是qApp在遍历A1的eventFitlers的过程中,然后C1又new了一堆B出来并给A1安装了它们作为事件过滤器,那么这些B的实例就会被添加到A1的eventFitlers前面,那么就相当于C1在A1的eventFitlers中被向后移了,之后qApp肯定又会遍历到C1,然后C1再弄一堆新的B实例…结果就是每过一遍C1,A1就多几个事件过滤器,这个列表永远也遍历不完
- 每个QObject将它的事件过滤器存在私有的数据结构中,其
-
-
包含子菜单的QMenu触发QAction以后立即删除
-
场景
- 假设一个QMenu对象
M1,M1的子菜单M2中的Action被单击以后,M1与M2的triggered信号都被触发,但是M2中的Action的快捷键被按下,只有M2的triggered信号会被触发,所以不得不给M1与M2的信号都连接一个槽,如果连接的是同一个槽,那么麻烦的问题就来了 - 在这个槽中,通过
qobject_cast<QMenu *>(sender())得到触发这个信号的QMenu实例,获取传入的action的associatedWidgets,对这两个进行比较,如果不同则不处理这次信号,可以避免同一次单击处理两次信号 - 由于
M2的信号先到,M1的后到,那么M2的被优先处理,M1的不会被处理 - 但是如果在处理
M2的信号过程中把这个action给删了(直接delete而不是调用deleteLater),例如直接执行M2的clear函数
- 假设一个QMenu对象
-
后果
Segmentation Fault
-
原因
- 在处理
M2的信号过程中删除了这个action,那么后面当M1的信号到的时候,此时传入的同一个action已经变成一个垃圾指针,调用它的associatedWidgets成员函数就会触发异常
- 在处理
-

884

被折叠的 条评论
为什么被折叠?



