Qt事件分發機制源碼分析之QApplication對象構建過程

咱們在新建一個Qt GUI項目時,main函數裏會生成相似下面的代碼:app

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);
    CQDialog dialog(NULL);
    dialog.show();
    return application.exec();
}

對應的步驟解釋以下函數

1.構建QApplication對象
2.構建CQDialog主界面
3.主界面顯示
4.QApplication對象進入事件循環處理直至退出
ui

上述步驟包含QApplication對象構建過程、主界面顯示過程、事件循環處理過程三個主題。this

這篇博文主要講解第一個主題,即QApplication對象構建過程。spa

QApplication類繼承關係以下圖所示插件

查看Qt源碼QApplication的構造函數code

#ifdef Q_QDOC
QApplication::QApplication(int &argc, char **argv)
#else
QApplication::QApplication(int &argc, char **argv, int _internal)
#endif
    : QGuiApplication(*new QApplicationPrivate(argc, argv, _internal))
{
    Q_D(QApplication);
    d->init();
}

QApplication父類QGuiApplication的構造函數orm

QGuiApplication::QGuiApplication(QGuiApplicationPrivate &p)
    : QCoreApplication(p)
{
}

能夠看到QGuiApplication的構造函數爲空內容,進入到QGuiApplication父類QCoreApplication的構造函數對象

QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
#ifdef QT_NO_QOBJECT
    : d_ptr(&p)
#else
    : QObject(p, 0)
#endif
{
    d_func()->q_ptr = this;
    // note: it is the subclasses' job to call
    // QCoreApplicationPrivate::eventDispatcher->startingUp();
}

其也沒有實際性的內容。blog

主要集中在QApplicationPrivateQGuiApplicationPrivateQCoreApplicationPrivate類的內部處理,這也是Qt一向的用法,即信息隱藏。

其類關係圖以下

所以函數調用返回到QApplication構造函數中,QApplicationPrivate::init函數被調用用於初始化操做

void QApplicationPrivate::init()
{
#if defined(Q_OS_MACOS)
    QMacAutoReleasePool pool;
#endif

    QGuiApplicationPrivate::init();

    initResources();

    qt_is_gui_used = (application_type != QApplicationPrivate::Tty);
    process_cmdline();

    // Must be called before initialize()
    qt_init(this, application_type);
    initialize();
    eventDispatcher->startingUp();

#ifdef QT_EVAL
    extern void qt_gui_eval_init(QCoreApplicationPrivate::Type);
    qt_gui_eval_init(application_type);
#endif
#ifndef QT_NO_ACCESSIBILITY
    // factory for accessible interfaces for widgets shipped with Qt
    QAccessible::installFactory(&qAccessibleFactory);
#endif

}

QGuiApplicationPrivate::init會調用QCoreApplicationPrivate::initQCoreApplicationPrivate::init會進行eventDispatcher的建立,以下代碼所示

#ifndef QT_NO_QOBJECT
    // use the event dispatcher created by the app programmer (if any)
    if (!eventDispatcher)
        eventDispatcher = threadData->eventDispatcher.load();
    // otherwise we create one
    if (!eventDispatcher)
        createEventDispatcher();
    Q_ASSERT(eventDispatcher);

    if (!eventDispatcher->parent()) {
        eventDispatcher->moveToThread(threadData->thread);
        eventDispatcher->setParent(q);
    }

    threadData->eventDispatcher = eventDispatcher;
    eventDispatcherReady();
#endif

基於多態性,QGuiApplicationPrivate::createEventDispatcher被調用

void QGuiApplicationPrivate::createEventDispatcher()
{
    Q_ASSERT(!eventDispatcher);

    if (platform_integration == 0)
        createPlatformIntegration();

    // The platform integration should not mess with the event dispatcher
    Q_ASSERT(!eventDispatcher);

    eventDispatcher = platform_integration->createEventDispatcher();
}

createEventDispatcher函數裏作兩件事情

1.建立平臺插件(Windows、Linux)
2.根據平臺插件建立eventDispatcher

以我在Windows平臺上開發爲例

1.建立QWindowsIntegration以及QWindowsGuiEventDispatcher
2.在QWindowsIntegration建立過程當中會生成QWindowsContext對象

QEventDispatcherWin32類繼承關係以下圖所示

所以,QApplication構造時建立了eventDispatcher

關於QApplication對象構建過程就講述完畢了,後續博文會看到eventDispatcher、QWindowsContext的用途

有部分代碼位於qtbase\src\plugins\platforms源碼目錄

相關文章
相關標籤/搜索