qt事件循环笔记

 QApplication a exec()程序启动,一直到exit()被调用才终止,所以说事件循环是伴随着Qt程序的整个运行周期!
QApplication a;
a exec();


简述事件循环流程:
主动创建派发事件sendEvent(阻塞 )/postEvent(不阻塞  处理之前就返回)/外部事件->(事件队列)notify处理所有通过Qt事件系统传递的事件并且调用notify_helper (notify方法中被调用,用于处理事件的分发和过滤) ->notify_helper会调用目标对象的 event方法(receiver->event(event))来分发事件;

notify和notify_helper部分源码:

可以这么说,每一个事件执行前,都要经过QApplication::notify,所以,我们可以重写notify来对事件做特殊处理。

bool QApplication::notify(QObject *receiver, QEvent *event)
{
   ...
   switch (e->type()) {
    ...
    case QEvent::Wheel: // User input and window activation makes tooltips sleep
    case QEvent::ActivationChange:
    case QEvent::KeyPress:
    case QEvent::KeyRelease:
    case QEvent::FocusOut:
    case QEvent::FocusIn:
    case QEvent::MouseButtonPress:
    case QEvent::MouseButtonRelease:
    case QEvent::MouseButtonDblClick:
    ...
    res = d->notify_helper(receiver, e);
    ...
}

处理事件过滤器
到这里调用链到了QCoreApplicationPrivate::notify_helper,这个方法比较重要,我们来看主体代码:

bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
{
    ...
    // send to all application event filters (only does anything in the main thread)
    if (QCoreApplication::self
            && receiver->d_func()->threadData->thread.loadAcquire() == mainThread()
            && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
        filtered = true;
        return filtered;
    }
    // send to all receiver event filters
    if (sendThroughObjectEventFilters(receiver, event)) {
        filtered = true;
        return filtered;
    }

    // deliver the event
    consumed = receiver->event(event);
    return consumed;
}

可以看到,流程中涉及两个事件过滤器的调用:sendThroughApplicationEventFilterssendThroughObjectEventFilters,事件过滤器调用完后,才是调用接收者的event函数。

对象的event方法
从QCoreApplicationPrivate::notify_helper代码可以看到,处理完事件接收者的事件过滤器后,就会调用接收者的event方法来处理事件。
每一个从QObject继承出来的子类都有event方法,都可以处理自己的事件。
我们简单看下QWidget的event方法:

bool QWidget::event(QEvent *event)
{
    ...
    switch (event->type()) {
    ...
    case QEvent::MouseMove:
        mouseMoveEvent((QMouseEvent*)event);
        break;

    case QEvent::MouseButtonPress:
        mousePressEvent((QMouseEvent*)event);
        break;

    case QEvent::MouseButtonRelease:
        mouseReleaseEvent((QMouseEvent*)event);
        break;

    case QEvent::MouseButtonDblClick:
        mouseDoubleClickEvent((QMouseEvent*)event);
        break;
        ...
}

 

notify 方法

notify 方法是 QCoreApplication(或其子类)的一个虚函数,用于接收并处理来自Qt事件系统的事件。当Qt事件系统检测到有事件发生时,它会调用 QCoreApplication 的 notify 方法,并将事件的目标对象(receiver)和事件本身(event)作为参数传递。

notify_helper 方法

notify_helper 方法是 QCoreApplicationPrivateQCoreApplication 的私有实现部分)的一个成员函数,它接收相同的参数(receiver 和 event)并执行事件的过滤和分发逻辑。这个方法是 notify 方法内部调用的一部分,用于实现更复杂的事件处理逻辑。

notify_helper 的工作流程

  1. 事件过滤器检查
    • 首先,notify_helper 检查当前是否在主线程中,并且事件是否应该通过应用程序级别的事件过滤器。这是通过调用 QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event) 实现的。如果事件被过滤器中的任何一个消费(即过滤器返回了 true),则 notify_helper 会将 filtered 设置为 true 并返回,表示事件已被处理,不再需要传递给目标对象。
  2. 对象级别的事件过滤器检查
    • 如果事件没有被应用程序级别的事件过滤器消费,notify_helper 接着会检查是否有任何对象级别的事件过滤器(即安装在目标对象或其父对象上的事件过滤器)应该处理该事件。这是通过调用 sendThroughObjectEventFilters(receiver, event) 实现的。同样,如果事件被消费,notify_helper 会返回 true
  3. 事件分发
    • 如果事件既没有被应用程序级别的事件过滤器也没有被对象级别的事件过滤器消费,notify_helper 会调用目标对象的 event 方法(receiver->event(event))来分发事件。event 方法是 QObject 类的一个虚函数,子类可以通过重写这个方法来提供对特定事件类型的处理。notify_helper 会返回 event 方法的返回值,该值通常表示事件是否被消费(true 表示消费,false 表示未消费)。

总结

notify 和 notify_helper 一起工作,构成了Qt事件处理机制的核心。notify 方法是Qt事件系统与应用程序之间的接口,而 notify_helper 则负责实现事件的具体过滤和分发逻辑。通过这种方式,Qt能够灵活地处理各种类型的事件,同时允许开发者通过安装事件过滤器来拦截和修改事件的传递过程。

通过上面的分析,可以获得5种处理或过滤事件的方法;1.重写事件; 2.event中处理;3.事件过滤器;4.notify;5QApplication安装事件过滤器

 

 

  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值