我們在新建一個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();
}
其也沒有實際性的內容。
主要集中在QApplicationPrivate
、QGuiApplicationPrivate
、QCoreApplicationPrivate
類的內部處理,這也是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::init
,QCoreApplicationPrivate::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源碼目錄