Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象)

2023-02-16,,,,

Qt中事件分发源代码剖析

Qt中事件传递顺序:

在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的。
下面举例说明:

1)首先看看下面一段示例代码:

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MouseEvent w;
    w.show();
    return a.exec();
    }

2)a.exec进入事件循环,调用的是QApplication::exec();

    int QApplication::exec()
    {
    return <span style="color:#ff6666;">QGuiApplication::exec();</span>
    }

3)QApplication::exec()调用的是QGuiApplication::exec();

    int QGuiApplication::exec()
    {
    #ifndef QT_NO_ACCESSIBILITY
    QAccessible::setRootObject(qApp);
    #endif
    return QCoreApplication::exec();
    }

4)QGuiApplication::exec()调用的是QCoreApplication::exec();

    int QCoreApplication::exec()
    {
    if (!QCoreApplicationPrivate::checkInstance("exec"))
    return -1;
    QThreadData *threadData = self->d_func()->threadData;
    if (threadData != QThreadData::current()) {
    qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
    return -1;
    }
    if (!threadData->eventLoops.isEmpty()) {
    qWarning("QCoreApplication::exec: The event loop is already running");
    return -1;
    }
    threadData->quitNow = false;
    QEventLoop eventLoop;
    self->d_func()->in_exec = true;
    self->d_func()->aboutToQuitEmitted = false;
    int returnCode = eventLoop.exec();
    threadData->quitNow = false;
    if (self) {
    self->d_func()->in_exec = false;
    if (!self->d_func()->aboutToQuitEmitted)
    emit self->aboutToQuit(QPrivateSignal());
    self->d_func()->aboutToQuitEmitted = true;
    sendPostedEvents(0, QEvent::DeferredDelete);
    }
    return returnCode;
    }

5)QCoreApplication::exec()调用eventLoop.exec()进行事件循环;

    int QEventLoop::exec(ProcessEventsFlags flags)
    {
    Q_D(QEventLoop);
    //we need to protect from race condition with QThread::exit
    QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
    if (d->threadData->quitNow)
    return -1;
    if (d->inExec) {
    qWarning("QEventLoop::exec: instance %p has already called exec()", this);
    return -1;
    }
    struct LoopReference {
    QEventLoopPrivate *d;
    QMutexLocker &locker;
    bool exceptionCaught;
    LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
    {
    d->inExec = true;
    d->exit = false;
    ++d->threadData->loopLevel;
    d->threadData->eventLoops.push(d->q_func());
    locker.unlock();
    }
    ~LoopReference()
    {
    if (exceptionCaught) {
    qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
    "exceptions from an event handler is not supported in Qt. You must\n"
    "reimplement QApplication::notify() and catch all exceptions there.\n");
    }
    locker.relock();
    QEventLoop *eventLoop = d->threadData->eventLoops.pop();
    Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error");
    Q_UNUSED(eventLoop); // --release warning
    d->inExec = false;
    --d->threadData->loopLevel;
    }
    };
    LoopReference ref(d, locker);
    // remove posted quit events when entering a new event loop
    QCoreApplication *app = QCoreApplication::instance();
    if (app && app->thread() == thread())
    QCoreApplication::removePostedEvents(app, QEvent::Quit);
    while (!d->exit)
    processEvents(flags | WaitForMoreEvents | EventLoopExec);
    ref.exceptionCaught = false;
    return d->returnCode;
    }

6)eventLoop.exec()调用QCoreApplication的processEvents进行事件分发;

7)调用notify进行分发

QCoreApplication::sendEvent、QCoreApplication::postEvent和QCoreApplication::sendPostedEvents都调用notify进行事件分发;

    bool QCoreApplication::notify(QObject *receiver, QEvent *event)
    {
    Q_D(QCoreApplication);
    // no events are delivered after ~QCoreApplication() has started
    if (QCoreApplicationPrivate::is_app_closing)
    return true;
    if (receiver == 0) {                        // serious error
    qWarning("QCoreApplication::notify: Unexpected null receiver");
    return true;
    }
    #ifndef QT_NO_DEBUG
    d->checkReceiverThread(receiver);
    #endif
    return receiver->isWidgetType() ? false :<span style="color:#ff6666;"> d->notify_helper</span>(receiver, event);
    }

8)notify调用notify_helper进行事件分发;

    bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
    {
    // send to all application event filters
    if (sendThroughApplicationEventFilters(receiver, event))
    return true;
    // send to all receiver event filters
    if (sendThroughObjectEventFilters(receiver, event))
    return true;
    // deliver the event
    return receiver->event(event);
    }

9)从上面第8步的代码可以看出事件传递

传递的顺序是:首先传递给全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象。

http://blog.csdn.net/chenlong12580/article/details/25009095

Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象)的相关教程结束。

《Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象).doc》

下载本文的Word格式文档,以方便收藏与打印。