QT Demo 之 calqlatr(1) main.cpp

其實從最開始要學習和分析Qt的Demo時選定的就是calqlatr工程,但是打開源碼一看,貌似難度高了點,這纔有了上面的幾篇基本控件的分析。從這一章開始,我要拿下calqlatr這個Demo項目了。

main.cpp

main.cpp中的代碼非常簡單:

#include "../../shared/shared.h"
DECLARATIVE_EXAMPLE_MAIN(demos/calqlatr/calqlatr)

DECLARATIVE_EXAMPLE_MAIN(NAME)是一個函數宏,其具體實現是在"../../shared/shared.h"頭文件中。

其實在之前分析的Demo中也有使用到這個函數宏,只不過當時重點在分析QML代碼上,沒有對DECLARATIVE_EXAMPLE_MAIN(NAME)函數宏詳細展開。這篇文章中就把它詳細解開。

#define DECLARATIVE_EXAMPLE_MAIN(NAME) int main(int argc, char* argv[]) \
{\
    QGuiApplication app(argc,argv);\
    app.setOrganizationName("Qt Project");\
    app.setOrganizationDomain("qt-project.org");\
    app.setApplicationName(QFileInfo(app.applicationFilePath()).baseName());\
    QQuickView view;\
    if (qgetenv("QT_QUICK_CORE_PROFILE").toInt()) {\
        QSurfaceFormat f = view.format();\
        f.setProfile(QSurfaceFormat::CoreProfile);\
        f.setVersion(4, 4);\
        view.setFormat(f);\
    }\
    view.connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit()));\
    new QQmlFileSelector(view.engine(), &view);\
    view.setSource(QUrl("qrc:///" #NAME ".qml")); \
    view.setResizeMode(QQuickView::SizeRootObjectToView);\
    if (QGuiApplication::platformName() == QLatin1String("qnx") || \
          QGuiApplication::platformName() == QLatin1String("eglfs")) {\
        view.showFullScreen();\
    } else {\
        view.show();\
    }\
    return app.exec();\
}

從宏的實現可以清洗的看出,實際上是一個通用的main()函數實現。

這個main()和我們之前在分析Window Demo程序時的main()函數基本結構都是一致的,但是也有區別之處:在Window的Demo中使用的是QQmlComponent,在這裏使用的是QQuickView。

QGuiApplication app

因爲這裏要創建的是GUI程序,故使用QGuiApplication。但是和之前Window Demo程序時的main()函數中的使用多了以下三行:

    app.setOrganizationName("Qt Project");\
    app.setOrganizationDomain("qt-project.org");\
    app.setApplicationName(QFileInfo(app.applicationFilePath()).baseName());\

先看一下organizationName和organizationDomain這兩個屬性的官方說明:

organizationName : QString
This property holds the name of the organization that wrote this application.
The value is used by the QSettings class when it is constructed using the empty constructor. 

organizationDomain : QString
This property holds the Internet domain of the organization that wrote this application.
The value is used by the QSettings class when it is constructed using the empty constructor.

看到這裏,我們知道organizationName和organizationDomain這兩個屬性實際上是在QSettings或者其他需要顯示app的organizationName和organizationDomain時使用的。


同理,applicationName屬性也是在QSettings或其他需要顯示app的Name時使用,這裏需要明確指出的是,app的title默認值就是使用applicationName的值。

QQuickView view

The QQuickView class provides a window for displaying a Qt Quick user interface.
This is a convenience subclass of QQuickWindow which will automatically load and display a QML scene when given the URL of the main source file. Alternatively, you can instantiate your own objects using QQmlComponent and place them in a manually setup QQuickWindow.

從上面的官方說明上可以看出,QQuickView類是QQuickWindow類的子類,是一種方便的創建Window的方法,不過相對於QQuickWindow還需要使用QQmlComponent來加載Qml的方法,QQuickView則是直接擴展了setSource方法,下面是一個示例:

QQuickView *view = new QQuickView;
view->setSource(QUrl::fromLocalFile("myqmlfile.qml"));
view->show();

在這裏也是通過setSource來指定需要加載的qml文件:

    view.setSource(QUrl("qrc:///" #NAME ".qml")); \
上面的#NAME就是DECLARATIVE_EXAMPLE_MAIN(NAME)函數宏的參數。

view.setResizeMode()

代碼中設置了resize模式:

    view.setResizeMode(QQuickView::SizeRootObjectToView);\

從官方文檔來看,有兩種resize模式,分別是:

  • QQuickView::SizeViewToRootObject:    The view resizes with the root item in the QML.
  • QQuickView::SizeRootObjectToView:    The view will automatically resize the root item to the size of the view.

但是從名字來看,這兩個模式一個是從View到RootObject,一個是從RootObject到View,具體什麼時候該用哪一個呢?這裏的說明比較簡單,看一下Detailed Description部分的詳細說明:

QQuickView also manages sizing of the view and root object.  By default, the resizeMode is SizeViewToRootObject, which will load the component and resize it to the size of the view.  Alternatively the resizeMode may be set to SizeRootObjectToView which will resize the view to the size of the root object.

那麼我們可以簡單的理解,就是如何自動調節root object和view的大小,只不過這裏對於所謂的root object具體是何物,沒有詳細解釋。此處暫留一個TODO:SizeViewToRootObject和SizeRootObjectToView的區別和如何使用它們。

view.show()

在設置完view的屬性之後,就可以顯示view了,在示例中使用下述代碼來顯示view:

    if (QGuiApplication::platformName() == QLatin1String("qnx") || \
          QGuiApplication::platformName() == QLatin1String("eglfs")) {\
        view.showFullScreen();\
    } else {\
        view.show();\
    }\

注意,這裏提到了QGuiApplication::platformName(),上面判斷的qnx和eglfs對於我們來說比較陌生,但是通過查看文檔我們瞭解到QGuiApplication::platformName()還包括一下幾種:

  • android
  • cocoa is a platform plugin for Mac OS X.
  • windows
  • ios
  • xcb is the X11 plugin used on regular desktop Linux platforms.
  • ...

那麼我們就可以很方便的判斷當前平臺是否是OS X、Linux、Window以及Android、IOS等等,至於哪些不常見的一些平臺,對於我來講能力有限不能展開。

在獲取了平臺信息之後,就可以選擇如何顯示view了,示例中針對qnx和eglfs進行了全屏顯示,其他都是採用平臺默認的顯示方式。除了上面兩種顯示方式,還有下面的一些函數用來指定如何顯示:

  • show():                   Shows the window, depending on the platform's default behavior for the window type and flags.
  • showFullScreen():  Shows the window as fullscreen.
  • showMaximized():   Shows the window as maximized.
  • showMinimized():    Shows the window as minimized.
  • showNormal():        Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen.

QSurfaceFormat

在創建完view之後,還有下述的一段代碼:

    if (qgetenv("QT_QUICK_CORE_PROFILE").toInt()) {\
        QSurfaceFormat f = view.format();\
        f.setProfile(QSurfaceFormat::CoreProfile);\
        f.setVersion(4, 4);\
        view.setFormat(f);\
    }\

通過添加打印,發現這裏的if根本沒有執行到,而且全局搜索QT_QUICK_CORE_PROFILE也沒有找到其他有定義該env的地方,故暫不對該部分代碼進行分析。

總結

這一章只是把幾乎每個Demo工程中都會見到的DECLARATIVE_EXAMPLE_MAIN(NAME)函數宏詳細分析了一下。從下一章開始,進入到calqlatr的qml代碼中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章