第53篇 Qt Quick项目详解

导语

前面我们一起创建了一个Qt Quick项目,并对里面的文件进行了简单的讲解,虽然这只是一个HelloWorld程序,但对于没有Qt Quick编程经验的同学来说,这个项目还是有点复杂。在这一篇中,我们将从最简单的QML文件讲起,然后逐渐丰富项目内容,帮助大家由浅及深的进行学习,进一步了解Qt Quick项目的构成。

环境:Windows 7 + Qt 5.5.0+ Qt Creator 3.4.2

目录

  • 一、创建空项目
  • 二、添加QML文件
  • 三、运行程序
  • 四、扩展QML程序
  • 五、添加C++代码
  • 六、使用资源文件

正文

一、创建空项目

1、首先打开Qt Creator,然后选择“新建文件或项目”菜单项,在选择模板页面选择“其他项目”分类中的“Empty qmake Project”,我们先来创建一个空项目,后面逐步往里面添加文件。点击“choose”按钮确定选择,如下图所示。

2、在项目位置页面,将项目名称修改为myqml,然后选择好创建路径。如下图所示。

3、后面的步骤直接使用默认设置即可。

二、添加QML文件

1、创建好的空项目只有一个.pro项目文件,现在里面的内容也是空的。我们先不去管它,下面向该项目中添加文件。在myqml文件夹上右击,在弹出的菜单中选择“添加新文件”,如下图所示。

2、在弹出的新建文件对话框中选择Qt分类中的“QML File(Qt Quick 2)”一项。如下图所示。(说明一下:这里要添加QML文件,模板可以选择Qt Quick 1、Qt Quick 2和QtQuickUI File三种,Qt Quick 1会导入QtQuick 1.1模块,里面的内容都是Qt 4时代的;而QtQuick 2导入的是QtQuick 2.0模块,是Qt 5中的新版本;QtQuick UI文件生成后会默认使用设计器,因为我们这一节直接讲代码,不涉及设计器的内容,所以不选择这个模板。其实,使用哪个模板都一样,因为到文件里面可以直接修改导入模块语句,初学者在这里不要纠结。)

3、下面设置文件的名称为main,路径保持默认即可,现在的路径就是项目源码路径。然后点击“下一步”按钮,如下图所示。

4、最后是项目管理页面,可以看到,新创建的文件默认添加到了myqml.pro项目中,直接点击“完成”按钮完成文件的添加建,如下图所示。

三、运行程序

1、可以看到添加的文件就是main.qml,后缀.qml表明该文件是一个QML文件,其内容如下。

import QtQuick 2.0
Rectangle {
    width: 100
    height: 62
}

这是一个最简单的QML文件,它会显示一个宽100像素高62像素的矩形。这里的import语句上一节已经提到过了,它会导入相应的模块,比如这里导入了QtQuick 2.0模块。下面的Rectangle是矩形对象,用来定义一个矩形项目(项目类似于C++中的窗口或者部件),里面的widthheightRectangle的属性,用来设置矩形相关参数。

2、QML文件与C++文件是不同的,它不需要进行编译,可以直接运行。在Qt中提供了两个运行QML文件的工具qmlviewer和qmlscene,前者是Qt 4时代的产物,主要用来显示导入了QtQuick 1.1模块的QML文件,而qmlscene用来显示导入了QtQuick 2.0以后版本的QML文件。选择“工具→外部→QtQuick→Qt Quick 2Preview”菜单项即可在qmlscene中显示现在打开的QML文档的内容。如下图所示。

运行效果如下图所示。

四、扩展QML程序

1、添加文本显示

可以看到现在的程序就是一个空白的窗口,什么都没有。下面我们来扩展该程序,将main.qml文件的内容更改如下:

import QtQuick 2.0
Rectangle {
    width: 100
    height: 62
    Text {
       text: "hello World"
    }
}

这里添加了一个Text对象,它用来显示一块文本,其text属性用来指定要显示的文本内容。下面先按下Ctrl+S快捷键保存该文件,然后在qmlscene中查看显示效果,如下图所示。

2、使用锚布局

我们看到现在可以显示hello world文本了,但是文本默认显示在了左上角,我们希望它可以在窗口中间显示,下面继续添加代码:

Text {
       text: "hello World"
       anchors.centerIn: parent
    }

这里使用了anchor锚的概念进行了布局,在QML中每一个项目都有一组无形的锚,分别在上、下、左、右、中心等处,它们可以定义项目自身和其他项目的相对位置。比如这里的centerIn就是指Text项目在parent项目的中心,这里的parent就是指Text的父项目Rectangle。在anchor后面一般指定其他项目的id,如果是父子项目,也可以像现在这样指定parent

下面先保存代码(以后每次修改都需要保存后才能显示,后面不再提醒),然后在qmlscene中运行,效果如下图所示。

3、添加鼠标互动。

前面的代码已经完成了一个简单的Hello World界面,下面我们添加代码实现点击界面退出程序的效果:

import QtQuick 2.0
Rectangle {
    width: 100
    height: 62
    Text {
       text: "hello World"
       anchors.centerIn: parent
    }
    MouseArea {
       anchors.fill: parent
       onClicked: {
           Qt.quit()
       }
    }
}

我们在Rectangle中又添加了一个MouseArea子对象,这个从字面上翻译就是鼠标区域,它是一个不可见的项目,就是说我们在窗口上并不能看到它的存在,通过该对象可以实现鼠标互动。anchors.fill是进行填充,这里就是将鼠标区域覆盖整个Rectangle窗口。onClicked其实就是Qt C++中的信号处理函数,这里一般叫做信号处理器,其语法是on<Signal>,所以这里就是Clicked单击信号的处理,当在窗口上单击鼠标后会执行Qt.quit()函数,这是个全局函数,执行结果就是使程序退出。

大家可以在qmlscene中运行程序,然后在窗口上点击鼠标查看运行效果。

4、使用组件

前面创建的是main.qml文件,本意是让其作为主要文件,成为程序的入口。但是如果按照现在的做法,程序越写越复杂,main.qml的内容会越来越多,越来越乱。为了避免在main.qml中添加过多的代码,我们一般将具体的实现代码放到单独的文件中。

下面首先在QML目录中添加新文件,如下图所示。

模板依然选择Qt分类中的QML File(QtQuick 2),文件名称设置为MyHelloWorld,请注意首字母要大写,如下图所示。

添加完成后,将main.qml中的内容全部复制粘贴过来,如下图所示。

下面我们修改main.qml文件的内容如下:

import QtQuick 2.0
Item {
    MyHelloWorld {
       anchors.fill: parent
    }
}

像这样在一个单独文档中的QML代码段,就定义了一个对象类型,它也叫做组件,这个文件的名称必须以大写字母开头。比如这里创建了一个MyHelloWorld类型,在其他QML文件中可以直接使用同一目录下自定义的对象类型,所以,我们在main.qml中直接创建了MyHelloWorld对象。这里根对象使用了Item,在Qt Quick中,所有可视项目都继承自Item,因为在main.qml中我们只需要创建一个窗口,不需要进行内容设置,所以一般使用Item即可,当然,如果想使用Rectangle等也是可以的。

使用组件除了可以简化代码外,更重要的是它可以被重复使用,如果在一个代码中需要多次使用相同的部件或者功能,将它们作为组件就没必要多次编写相同的代码了。大家可以保存文件后在qmlscene中运行程序,查看效果。

5、id属性和属性别名

前面提到过id属性,其实它就是一个对象的名字,来唯一确定一个对象,在其他对象中可以通过id引用该对象。下面我们将MyHelloWorld.qml文件的内容更改如下:

import QtQuick 2.0
Rectangle {
    width: 100
    height: 62
    property alias mArea: mouseArea
    Text {
       text: "hello World"
       anchors.centerIn: parent
    }
    MouseArea {
       id: mouseArea
       anchors.fill: parent
    }
}

这里我们首先更改了MouseArea对象,设置其idmouseArea,这样就可以在Rectangle中通过mouseArea来访问MouseArea对象。为了可以在MyHelloWorld.qml文件外访问Rectangle内的子对象,我们需要在Rectangle中自定义属性,并且该属性需要是子对象的属性别名,例如这里我们声明了一个mArea属性,alias表明mAreamouseArea的别名,这样在MyHelloWorld.qml文件外就可以通过mArea来操作MouseArea对象了。

下面我们修改main.qml文件:

import QtQuick 2.0
Item {
    MyHelloWorld {
       anchors.fill: parent

       mArea.onClicked: {
           Qt.quit()
       }
    }
}

这里直接在MyHelloWorld对象中通过mArea调用了onClicked处理器。现在保存文件,然后通过qmlscene运行程序,查看效果。

到这里我们已经基本还原了上一篇中创建的Qt Quick应用中qml文件的内容,从最简单的程序开始,逐渐丰富代码,现在大家应该已经对QML程序有了一定的认识。下面我们继续丰富程序,使其成为一个可以编译运行的项目。

五、添加C++代码

1、添加main.cpp文件。首先在myqml目录上右击,选择“添加新文件”,如下图所示。在弹出的对话框中选择C++分类中的“C++Source File”。

2、文件名称设置为main,如下图所示。

3、添加完成后将main.cpp文件的内容修改为:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("../myqml/main.qml")));
    return app.exec();
}

这里主要就是普通的Qt C++中main()函数,关键是其中创建了QQmlApplicationEngine对象来加载QML文件,这个是固定的用法。因为现在编译运行程序的本地目录是自动生成的目录,它与myqml源码目录是同级目录,所以加载main.qml文件需要指定相对路径。

2、更改项目文件。现在在myqml.pro文件中已经自动添加了一些代码,我们只需在最后添加一句代码:

QT += quick qml

这样就表明项目中使用了QtQuickQtQml模块。

3、修改main.qml文件。要在C++程序中使用QQmlApplicationEngine加载QML文件,要求顶层窗口使用Window项目,就是在main.qml中的根对象使用Window对象来代替Item对象,因为Window默认是不显示的,所以还有设置其visible属性为true,这个也是固定用法,大家以后照着做即可。修改后的main.qml文件如下:

import QtQuick 2.0
import QtQuick.Window 2.0
Window {
    visible: true
    MyHelloWorld {
       anchors.fill: parent
       mArea.onClicked: {
           Qt.quit()
       }
    }
}

这里还导入了QtQuick.Window 2.0,这是因为该模块包含了Window类型。现在我们可以按下Ctrl+R快捷键来编译运行程序了,效果如下图所示。

六、使用资源文件

因为QML文件是普通的文本文件,但在程序运行时需要使用这些文件来创建界面,将其直接放在程序外是不安全的,所以我们的做法是将QML文件放到资源文件中。

1、添加资源文件。继续在myqml目录上右击,选择添加新文件,模板选择Qt分类中的“Qt Resource File”,如下图所示。

然后将文件名称设置为“qml”,如下图所示。

2、文件创建好之后会自动打开,这里我们先点击“添加”按钮,选择“添加前缀”,如下图所示。

这里将前缀设置为/,如下图所示。(其实前缀使用什么都可以,这里为了简便,只保留斜杠)

3、再次点击“添加”按钮,这次选择“添加文件”,如下图所示。

在弹出的对话框中,选择源码目录中所有的QML文件,如下图所示。完成后点击Ctrl+S保存资源文件。

4、添加完成以后,可以在左边文件列表中看到资源文件。如下图所示。

5、因为已经在资源文件中添加了QML文件,所以以前在项目中的QML文件就不再需要了。双击打开myqml.pro文件, 然后将其中的:

DISTFILES += \
    main.qml \
    MyHelloWorld.qml

代码删除掉,点击Ctrl+S保存项目文件。这时项目中的文件列表如下图所示。

6、最后修改main.cpp文件。因为现在使用了资源文件,所以要更改main.cpp文件中QML文件的路径,将其修改为:

engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

到这里整个项目就修改完成了,大家可以运行程序,查看效果。这个项目将作为我们的模板,后面的章节会在这个项目的基础上进行修改来讲解,项目的创建过程就不再赘述。

小结

这一篇中我们将上一篇讲解的Qt Quick项目进行拆解分析,以初学者的角度,从最简单的几行代码开始,一点点丰富程序,一步步进行分析讲解,最终还原了整个程序。本节内容让大家可以从根本上掌握Qt Quick程序的构建,并且也提供了一种学习的方法,一种分析大型复杂程序的方法,就是所谓的剖析法,希望大家用心过一遍,为以后的学习打好基础。