Qt 踩坑记录

2 篇文章 0 订阅

Qt 踩坑记录

吃一堑长一智


  1. 事件过滤器处理函数中添加事件过滤器

    • 场景

      • 假设有A、B、C三个类,它们都是QObject的子类
      • 实例A1安装了实例C1作为事件过滤器
      • QApplication发送了一个事件eA1
      • C1捕捉到这个事件并对其进行处理,在处理的过程中创建了一个或多个B的实例,创建完后立刻给A1安装这些B的实例作为事件过滤器
    • 后果

      • C1eventFilter函数处理完本次的事件e后,控制流又会莫名其妙进入C1eventFilter函数中,它又要处理一次事件e,处理完后控制流又进入C1eventFilter函数,成为一个死循环永远出不去
    • 原因

      • 每个QObject将它的事件过滤器存在私有的数据结构中,其d_ptr中的extraDataeventFilters就是存放它事件过滤器的列表
      • QCoreApplication在执行notify后,会调用QCoreApplicationPrivate::sendThroughObjectEventFilters函数,然后从头开始遍历事件接收者的这个eventFilters列表,一个个调用它们的eventFilter函数,如果其中有一个返回了true,那么就算拦截成功,事件将不会进一步传播
      • 对一个QObject的实例执行installEventFilter是将新的事件过滤器实例加入到这个列表的头部,所以这就是后装的事件过滤器优先过滤事件的原因
      • 所以答案已经很明确了,C1在处理事件e的时候,就是qApp在遍历A1eventFitlers的过程中,然后C1new了一堆B出来并给A1安装了它们作为事件过滤器,那么这些B的实例就会被添加到A1eventFitlers前面,那么就相当于C1A1eventFitlers中被向后移了,之后qApp肯定又会遍历到C1,然后C1再弄一堆新的B实例…结果就是每过一遍C1A1就多几个事件过滤器,这个列表永远也遍历不完
  2. 包含子菜单的QMenu触发QAction以后立即删除

    • 场景

      • 假设一个QMenu对象M1M1的子菜单M2中的Action被单击以后,M1M2triggered信号都被触发,但是M2中的Action的快捷键被按下,只有M2triggered信号会被触发,所以不得不给M1M2的信号都连接一个槽,如果连接的是同一个槽,那么麻烦的问题就来了
      • 在这个槽中,通过qobject_cast<QMenu *>(sender())得到触发这个信号的QMenu实例,获取传入的actionassociatedWidgets,对这两个进行比较,如果不同则不处理这次信号,可以避免同一次单击处理两次信号
      • 由于M2的信号先到,M1的后到,那么M2的被优先处理,M1的不会被处理
      • 但是如果在处理M2的信号过程中把这个action给删了(直接delete而不是调用deleteLater),例如直接执行M2clear函数
    • 后果

      • Segmentation Fault
    • 原因

      • 在处理M2的信号过程中删除了这个action,那么后面当M1的信号到的时候,此时传入的同一个action已经变成一个垃圾指针,调用它的associatedWidgets成员函数就会触发异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值