Qt中事件分发源代码剖析

来源:互联网 发布:java代码的基本格式 编辑:程序博客网 时间:2024/06/06 16:57

                   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 QGuiApplication::exec();}

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 : d->notify_helper(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步的代码可以看出事件传递

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

1 0