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


我們在新建一個Qt GUI項目時,main函數里會生成類似下面的代碼:

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對象進入事件循環處理直至退出

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

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

QApplication類繼承關系如下圖所示

查看Qt源碼QApplication的構造函數

#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的構造函數

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

其也沒有實際性的內容。

主要集中在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源碼目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM