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代码中。

时间: 2024-08-07 16:30:45

QT Demo 之 calqlatr(1) main.cpp的相关文章

QT Demo 之 calqlatr(3) calculator.js

在分析完main.cpp和calqlatr.qml之后,就到了计算器的具体逻辑部分,即当用户在UI上点击数字或操作符时,是如何存储数据.计算结果以及显示在UI上?本篇通过分析calculator.js来详细展开. 入口函数 用户在UI上只有两种操作,分别是:点击数字和点击运算符,产生的操作就会触发下述处理: function operatorPressed(operator) { CalcEngine.operatorPressed(operator) } function digitPress

QT Demo 之 calqlatr(2) calqlatr.qml

import QtQuick 2.0 import "content" import "content/calculator.js" as CalcEngine 同样,这次我们针对qml代码开始的最常见的import部分也不放过了,也要至少做到基本了解和使用. 在Qml中如果需要使用系统组件,必须在开始进行声明.对于自定义的组件也需要在开始的时候import进来,并且需要注意的是,系统组件直接通过名称即可,而对于自定义组件,需要使用""包起来.

QT Demo 之 window(3) Qt.quit()

在上一章<QT Demo 之 window(2) Splash>学习中留下一个TODO没有解决,就是在示例代码中有这样的一段: MouseArea { anchors.fill: parent onClicked: Qt.quit() } 其本意就是在显示Splash Screen的时候,如果点击Splash Screen图片就会退出整个程序,但实际结果就是报了一行错误: Signal QQmlEngine::quit() emitted, but no receivers connected

qt demo pro

qt demo pro qtdemo.pri TEMPLATE = app QT_VER = $$[QT_VERSION] QT_PATH = $$[QT_INSTALL_PREFIX] #message(Qt version is $$QT_VER) #message(Qt install prefix is $$QT_PATH) QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += debug_and

QT Demo 之 window(5) window.qml

在分析了main.cpp.Splash.Qt.quit()以及ScreenInfo之后,我们终于开始了正题:window.qml. window.qml的主体结构 window.qml主体是一个QtObject,其中包含了4个子元素:palette.controlWindow.testWindow和splashWindow: QtObject { property real defaultSpacing: 10 property SystemPalette palette: SystemPale

QT Demo 之 window(2) Splash

在QT Demo 之 window一章我们学习了在C++层的QQuickWindow的一些知识,这一章我们重点看一下源码中的Splash.qml文件,该文件给我们演示了如何使用splash screen来显示应用的启动及界面. 关于应用的启动界面,有一个最直观也是比较常见的例子就是photoshop,下图就是PS启动时显示的界面: 在这个例子里也是先显示一个Qt的Logo,然后再进入到主应用窗口中. 源码结构 Splash.qml实现了一个自定义的window来完成Splash screen的功

QT Demo 之 window

我们开始学习GUI编程中的一个超级重要的概念,那就是Window,不过在Qt中有很多种Windows,今天我学习的是QQuickWindow,顾名思义,就是用来显示QML场景的窗口. 在这一章,我们从cpp代码开始分析,先看一下main.cpp的代码: int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); QQmlEngine engine; QQmlComponent component(&engine); QQ

QT Demo 之 threading(3) triangle

同<QT Demo 之 threading(2) Spinner>一样,这一章也是把<QT Demo 之 threading>中的一个和threading完全独立的部分拿出来分析一下. 在中的WorkerScript.onMessage函数中有如下的调用,用来计算给定row和column下计算triangle的值: WorkerScript.onMessage = function(message) { //Calculate result (may take a while, u

QT Demo 之 threading(2) Spinner

在QT Demo 之 threading一章中我们使用到了Spinner,但是由于Spinner本身和thread部分关系不大,而是作为一个独立的自定义组件,因此我们在这一章中单独讲解. Spinner定义在threading/workerscript/Spinner.qml文件中,由一个Text和Rectangle组成: Rectangle { width: 64 height: 64 property alias value: list.currentIndex property alias