Qt 5入门指南之Qt Quick编程示例

编程示例
html

          使用Qt建立应用程序是十分简单的。考虑到你的使用习惯,咱们编写了两套教程来实现两个类似的应用程序,可是使用了编程

不一样的方法。在开始以前请确保你已经下载了QtSDK的商业版本或者开源版本,而且你也已经熟悉了Qt开发工具QtSDK网络

提供了QtCreator集成开发环境使得开发Qt的应用程序十分简单。app

用户界面的选择

        除了直观上知道Qt是跨平台的,提供了包括线程网络通讯以及视频回放和网络摄像头等的跨平台抽象外,Qt提供了两种编辑器

独立的方法建立用户界面。函数

QtQuick模块为建立流畅的、活生生的用户界面提供了一种标记语言。这种方式适合那些须要动画元素的界面,以及应用程序工具

主要运行在小屏幕和多点触控的设备上的场景。布局

QtWidgets模块针对传统桌面提供了更多的支持,和目标平台作了更多的集成,不管目标平台是MacOSX,Windows,KDE还会Gnome。它是一个很是高效的基于C++的类库,包含了不少常见的用户界面组件,你能够很是容易的为这些已存在的组件开发工具

扩展新的功能。动画

        你选择那个模块来建立用户界面取决于你想建立怎样的应用程序。其它的方法在余下的Qt库中都是同样的,因此你能够尽

可能的将应用程序中逻辑处理的代码写得更加独立一些。当你熟悉了下面两个示例,你能够再作决定选择哪个模块来建立用

户界面。对于更加详细的信息,能够查看用户界面信息。

教程

这里有两个用于建立两个类似应用程序的例子。一个是使用QtQuick建立用户界面,而另外一个则是使用QtWidgets来建立用户界面。

 

使用QtQuick开始编程

        欢迎来到QML的世界。在这个示例中咱们将会使用QML建立一个简单的文本编辑器应用程序。在阅读完这个指南以后,

你应该可使用QML和QtC++开发本身的应用程序。

QML构建用户界面

        本应用程序是一个简单的文本编辑器,能够加载、保存和执行一些文本的操做。这个指南将会包含两个部分。第一部分将会

涉及到应用程序的布局以及使用QML语言。在第二部分,咱们将会使用QtC++实现文本的加载和保存。使用Qt的元对象系统咱们

能够将C++的功能做为QML元素的属性使用。使用QML和QtC++,咱们能够将界面逻辑和应用程序逻辑分离开。


 

最终的源代码在examples/tutorials/gettingStartedQml目录。你也许须要先编译examples/tutprials/gettingStartedQml/filedialog目录下的

C++插件。这一步会将C++插件放在QML可以找到的目录下。要启动这个应用程序,仅仅须要使用qmlscene工具,将QML做为

参数传递给这个工具。C++的部分假设了阅读者已经掌握了基本的Qt编译过程。

教程章节:

  1. 定义按钮和菜单

  2. 实现菜单栏

  3. 编译文本编辑器

  4. 装饰文本编辑器

  5. 使用QtC++扩展QML

定义一个按钮和菜单

基本组件——按钮

        咱们以构建一个按钮开始咱们的文本编辑器。在功能上,按钮有一个鼠标敏感区域和一个标签。当用户点击按钮的时候,

按钮执行一个动做。

        在QML中,最基本的可视化单元就是矩形(Rectangle)元素。矩形元素具备控制元素外观和位置的属性。

        首先,导入QtQuick2.0容许qmlscene工具加载QML元素以便稍后使用。这一行代码在全部的QML文件中都存在。须要注意

的是,咱们导入Qt的模块的时候也导入了版本号。

        这个简单的矩形有一个惟一的标签”simplebutton”,这就是id属性。矩形元素的属性是经过依次罗列属性,中间以分号间隔,

而后就是属性的值。在示例代码中,”grey”颜色就绑定到了矩形的颜色属性。相似地,咱们也绑定了该矩形的高度和宽度。

        Text元素是一个不可编辑的文本区域。咱们给这个文本框命名为”buttonlabel”。咱们经过将值绑定到”text”属性来设置该文本

框的文字。这个文本框在矩形的中间,咱们将文本框的”anchors”设置为其父亲,也就是前面提到的simplebutton。Anchors也能够

绑定到其它元素的anchors,使得布局更加的简单。

        咱们将这些代码保存为SimpleButton.qml。使用这个文件的文件名做为参数调用qmlscene工具,将会出现以下的效果:


 

         要实现按钮的功能,咱们可使用QML的事件处理机制。QML的事件处理机制和Qt的信号-槽机制十分相似。信号被发射

而后关联的槽函数被调用。


 

         在咱们的simplebutton矩形中,咱们包含了一个MouseArea元素。MouseArea元素描述了可交互的区域,也就是鼠标的移动会

被检测的区域。在这个例子中,咱们将MouseArea的anchor设置为它的父亲,也就是前面提到的simplebutton。Anchors.fill是获取

指定属性的一种语法表达方式。fill是属性簇anchors中的一个特定属性。QML使用了基于anchor的布局,元素能够anchor其它的元

素,建立健壮的布局。

        当鼠标在MouseArea区域中移动时MouseArea有许多事件处理者。其中的一个事件处理者就是onClicked,该事件处理会在允

许鼠标点击的区域中点击鼠标时候被调用,默认是左键单击。咱们能够将一个动做绑定到onClicked处理句柄。在咱们的示例中

,当鼠标点击时,console.log()输出文本。Console.log()函数是一个有用的调试输出函数。

         以下的代码足够完成显示按钮且在鼠标单击的时候输出文本。


 

         一个功能齐全的按钮在Button.qml中。示例代码中有部分被省略了,由于这些代码要么在以前介绍过了,要么就是与本章

介绍的内容不是很相关。

        咱们可使用属性类型名称的语法来自定义属性。在示例代码中,buttonColor属性就是自定义的而且被赋值为”lightblue”。buttonColor在后面就被使用到了,用来根据不一样操做填充不一样的颜色。值得注意的是,属性的赋值使用的是”=”

而属性的值绑定使用的则是”:”。自定义的属性使得内部元素的可见范围能够超出矩形的范围。QML基本类型有int,string,real和variant经过绑定onEntered和onExited信号处理到颜色上,当鼠标停留在按钮之上,按钮的边框将会变为黄

颜色,而且在鼠标离开按钮的时候恢复为原来的颜色。

         咱们经过将signal关键字放在信号名称以前,自定义了一个buttonClick()信号在Button.qml中,全部的信号的处理者都是自动

被建立的,这是经过简单在信号的名字前面加上”on”这个单词。显然,onButtonClick就是buttonClick的处理者。onButtonClick

被赋予一些动做。在咱们的按钮示例中,onClicked鼠标处理者将会简单的调用onButtonClick,功能就是现实一个文本。

onButtonClick使得外部对象能够十分轻易的获取按钮的鼠标区域。例如:将设有许多的元素,这些元素拥有许多的MouseArea

那么一个buttonClick信号能够在许多的MouseArea作出区分,使得分别处理几个MouseArea更加简单。

         咱们如今已经具有了基本的知识:在QML中实现基本元素并能够处理鼠标移动事件。咱们在一个巨型中建立一个文本框,自定义了属性,针对鼠标移动实现了相应的处理。在元素中建立元素的思想贯穿着整个示例。

如今该按钮尚未什么用,除非他做为组件能够执行一些动做。在下面一节,咱们将会快速的建立一个菜单,包含几个这样的按钮。


 

建立一个菜单页

         在这一阶段,咱们将会介绍如何在一个单独的QML文件中建立元素并指定动做。在这一节,咱们将会介绍如何导入QML元素

及如何使用已经存在的组件构建新的组件。

        菜单显示了一个列表内容,每个元素都用执行一个特殊动做的功能。在QML中,咱们可使用几种方式建立菜单。首先咱们会建立一个包含按钮的菜单,每个按钮执行不一样的动做。菜单的代码在文件FileMenu.qml中。


 

      上面的语法展现了如何导入关键字。这里须要使用JavaScript文件,或者使用不在同一目录下的QML文件。由于Button.qml文件和FileMenu.qml文件在同一个目录下,所以咱们无需导入Button.qml文件就可使用它。咱们能够直接经过声明Button()建立按钮,

相似Rectangle的声明。


 

           在FileMenu.qml文件中声明了三个Button元素。它们都声明在一个Row元素内。该元素将其子元素水平放置。Button是在Button.qml文件中声明的,这种用法和上一节的用法一致。在新建立的button中,咱们能够将其属性绑定为新值,覆盖它们在Button.qml中绑定的默认值。exitButton按钮在被按下的时候整个应用程序就会退出。值得注意的是:在Button.qml中定义的信号onButtonClick将会在FileMenu.qml中被调用,除了exitButton的onButtonClick事件处理者。


 

Row是在一个Rectangle中声明的,建立了一个用于防止按钮的矩形容器。这个矩形建立了一个间接的方式用于组织在一个菜单中

的按钮行。编辑菜单的声明和以前菜单声明十分相似。菜单中的按钮的标签为:Copy,Paste和SelectAll


 

实现一个菜单栏

         咱们的文本编辑程序须要使用菜单栏来显示菜单。菜单栏将会切换到不一样的菜单,而且用户能够选择那些菜单能够显示。

菜单的切换意味着菜单须要更多的结构而不只仅是将它们成行的显示出来。QML使用模型和视图来组织数据以及显示结构化的

数据。

使用数据模型和视图

        QML有不一样的数据视图来显示数据模型。咱们的菜单栏会将菜单以列表的方式显示出来,也包含一个用于显示菜单名的头部。菜单列表是在VisualItemModel中声明的。VisualItemModel元素包含那些已经具备视图的元素,例如矩形以及导入的UI元素。其它的

模型类型,例如ListModel元素须要一个代理来显示它的数据。

         咱们在menuListModel中声明两个可视化元素:FileMenu和EditMenu。我定制了这两个菜单而且使用ListView来显示它们。MenuBar.qml文件包含了QML声明,一个简单的编辑菜单定义在EditMenu.qml文件中:

         ListView元素将会依照代理来显示模型。代理可能声明模型元素以Row元素显示,也可能以网格的方式显示。咱们的menuListModel已经包含了可视化元素,所以,咱们不须要声明代理。


 

         另外,ListView继承自Flickable,使得列表能够响应鼠标的拖拽以及其它的一些手势。上面代码的最后部分设置了Flickable

属性用于建立咱们想要的滑动操做。特别是highlightMoveDuration属性改变滑动转换的周期。一个highlightMoveDuration使得菜单

间的切换更加缓慢。

        ListView经过一个索引(index)来维护模型元素,而且模型中的每个可视化元素均可以经过索引来获取,索引的顺序是根据

元素被声明的顺序定义的。改变currentIndex的值将会导ListView中高亮的元素改变。咱们菜单栏的头部证实了这种效果。这里有

两个按钮,点击任何一个都会切换当前的菜单。当点击fileButton的时候,菜单切换到FileMenu,而且索引变为0,由于FileMenu在menuListModel中是最早声明的,editButton相似。labelList矩形有一个取值为1z变量,这意味着它是在菜单栏的上

面显示(空间坐标系)z值较大的元素始终在z值较小的元素的上面显示。默认的z值是0


 

目前建立的菜单栏仅仅具备菜单切换的效果,经过点击头部的两个按钮来进行切换:


 

构建文本编辑器

声明一个文本区域(TextArea)

        若是咱们的文本编辑器不具备一个可编辑的区域,那么他就不能被称为文本编辑器。QML的TextEdit元素容许声明一个

多行编辑的文本区域。TextEdit元素和Text元素是有区别的,后者不容许用户对文本进行编辑。


 

        上面设置了编辑器的前景色属性和环绕文字的模式。TextEdit区域是包含在一个flickable的区域中的,这确保了当文字光标

了当前的显示区域,那么文本内容会自动滚动。函数ensureVisible()将会检查鼠标是否处在可见区域的外面而且根据检查的结果

移动滚动文本区域。QML使用JavaScript语法做为其脚本,正如前面提到的,JavaScript能够导入而且在QML中使用。


 

为文本编辑器组装组件

         咱们如今已经准备好了使用QML为咱们的文本编辑器建立布局。文本编辑器包含两个组件,已经建立的菜单栏和文本区域。QML容许咱们重用这些组件,所以咱们能够经过导入组件以及在必要的时候作一些定制来简化咱们的代码。咱们的文本

编辑器将窗口分为两个部分:屏幕的1/3用来显示菜单栏,另外的2/3用来显示文本区域。菜单栏在其余的元素上面显示(空间坐标系)


 

       经过导入可重用的组件,咱们的文本编辑器的代码看起来更加简单了。咱们能够定制本身的主应用程序而没必要担忧那些已经

指定动做的属性。使用这种方法,应用程序的布局和UI组件能够更加简单的被建立。


 

装饰文本编辑器

实现一个绘图的接口

         咱们的文本编辑器看起来十分的简单,所以咱们须要装饰一下。使用QML,咱们能够为咱们的文本编辑器定义转换和动画。

咱们的菜单栏占据1/3的屏幕,所以只在咱们须要的时候才显示它这个功能将会十分有用。

        我添加了一个绘画的接口,在咱们单击的时候,该接口将会收起或者展开菜单栏。在咱们的实现中,咱们使用了一个十分小

的矩形用于鼠标点击。绘画接口和应用程序都有两种状态:绘画接口是打开的和绘画接口是关闭的。绘画(drawer)元素是一个矩形,可是它的高度很小。这里有一个内嵌在绘画元素中间的Image元素,用于展现一个箭头图标。绘画元素将会经过screen标签赋予整个

应用程序一个状态,不管用户在何时点击鼠标区域


 

          一个状态仅仅是定义在State元素内部的一系列配置的集合。咱们能够列举一系列的状态经过绑定到states属性。在咱们的

应用程序中,两种状态分别被称为DRAWER_CLOSED和DRAWER_OPEN。元素的配置都是在PropertyChanges中声明的。在DRAWER_OPEN状态中,有四个元素将会被改变属性。第一个目标,menubar将会改变本身的y属性为0。相似的textArea在DRAWER_OPEN状态中将会下降到一个新的位置。


 

        状态的转变是突兀的而且是须要作平滑转换的。在状态之间的转换是经过Transition元素定义的,定义好了以后能够绑定到

元素的transitions属性。咱们的文本编辑器有一个状态转换器。咱们的文本编辑器须要在DRAWER_OPEN和DRAWER_CLOSE

两种状态之间转换。重要的是,转换器须要一个from状态和一个to状态,咱们可使用*号通配符将该转换器应用于全部的状态

转换。

         在状态的转换过程当中,咱们能够为属性的变化指定动画。咱们的menuBar位置在y:0到y:-partition以前转换,咱们可使用NumberAnimation元素使得这个转换过程更生动。咱们声明了目标属性将会动画必定时间,而且使用特定的曲线。一个曲线

控制着动画的转换以及状态转换间的动做。咱们选择的特定曲线是Easing.OutQuint,该曲线在接近终点的时候运动速度变慢。

能够看看有关QML动画的内容。


 

        另外一种方式实现属性变化时候的动画效果就是声明一个Behavior元素。一个转换器仅仅在状态改变的时候工做,然而Behavior

能够在通常属性发生改变的时候工做。在文本编辑器中,当箭头的旋转属性改变时,箭头有一个NumberAnimation的动画。


 

       回到咱们对于组件的状态和动画知识,咱们能够提升咱们组件的表现力。在Button.qml中,在按钮被单击的时候,咱们能够

添加颜色(color)和比例(scale)属性改变。颜色的动画使用的是ColorAnimation元素数量的动画使用的是NumberAnimation。下面使

用的”onpropertyName”的语法形式对于目标是单个属性而言是十分有帮助的。


 

         另外,咱们能够经过使用颜色效果,例如:光栅效果等来加强QML组件的表现力。声明一个Gradient元素将会覆盖该元素的color属性。你能够在gradient中使用GradiendStop元素声明一种颜色。梯度(gradient)属性使用的是比例值,介于0.0和1.0之间。


 

        这个梯度值是被菜单栏使用的。最初的颜色是0.0,最后的则是1.0.

接下来怎么作

        咱们已经完成了一个简易的文本编辑器的界面。接下来咱们的UI界面已经完成,那么咱们就可使用Qt和C++来完成程序的逻辑部分。QML最为一个不错的原型工具,将应用程序的逻辑部分和UI设计隔离开。


 

使用Qt Cpp扩展QML

如今,咱们已经有了文本编辑框的布局,咱们如今就使用C++实现文本编辑框的功能部分。使用QML和C++容许咱们使用Qt建立

应用程序的逻辑部分。咱们可使用Qt的Quick类在C++应用程序中建立QML上下文,而且使用QQuickView显示QML元素。可选的,咱们也能够将C++代码导出为一个qmlscene工具能够读取的插件。在本示例中,咱们将会使用C++实现加载和保存文本的功能,而且将C++代码导出为一个插件。在这种方式下,咱们仅仅须要直接加载QML文件,而不是运行可执行程序。

导出C++类到QML

        咱们使用Qt和C++实现加载和保存文本的功能,经过注册C++的类和方法均可以在QML中被调用。C++类须要被编译为Qt

件,而且QML文件须要知道这个插件所处目录。

对于咱们的文本编辑器程序来讲,咱们须要建立以下的内容:

  1. Directory类,该类用于处理与目录相关的操做;

  2. File类,该类继承自QObject,列出一个目录下的全部文件;

  3. 插件类,该类将会注册到QML上下文中;

  4. Qt工程文件,使得这个Qt工程被编译成插件;

  5. 一个qmldir文件,用于告诉qmlscene工具插件类所处的目录。

编译Qt插件

        要编译一个插件,咱们须要将下面的内容放置到Qt工程文件中。首先是必须添加到Qt工程文件中的源文件,头文件以及Qt模块。全部的C++代码和工程文件都在filedialog目录下:


 

        特别须要注意的是,咱们将qml模块也链接到该工程中,而且配置为插件模式,使用lib模板。咱们将编译生成的插件放置在

上一层的plugins目录下。

注册一个类到QML


 

       咱们须要使用Q_PLUGIN_METADATA宏来导出插件。注意,在咱们的dialogPlugin.h文件中,咱们将Q_OBJECT宏放置在咱们

类的最上面。由于咱们须要对工程文件运行qmake来产生必要的元对象代码。

        咱们的插件类:DialogPlugin是QQmlExtensionPlugin的一个子类。咱们须要实现继承的方法:registerTypes()。dialogPlugin.cpp

件内容以下:


 

        registerTypes()方法将咱们的File和Directory类注册到QML中。该方法须要类的名称做为它的模板,一个主版本号,一个次版本

号以及类名。

在C++类中建立QML属性

        咱们可使用C++Qt的元对象系统来建立QML元素和属性。咱们可使用信号-槽机制实现属性,使得Qt能够识别这些属性。而后,这些属性就能够在QML中使用了。

        针对咱们的文本编辑器应用,咱们须要加载和保存文本。典型地,这些特性须要包含一个文件对话框。幸运地是咱们可使用QDir、QFile和QTextStream来实现目录的读取以及输入输出流。


 

        Directory类使用了Qt的元对象系统来注册一些属性以便完成文件处理。Directory类将会被做为一个插件导出,而且在QML中做为Directory元素使用。每个使用Q_PROPERTY宏定义的属性都是一个QML属性。

       Q_PROPERTY定义一个读和写的属性就比如是元对象系统中读和写函数同样。例如:filename属性,是QString类型,可以使用filename()方法读取,使用setFilename()设置。另外,这里有一个信号关联到了filename属性:filenameChanged(),当filename属性

改变的时候就会发射这个信号。读和写函数在头文件中是以public关键字声明的。

         相似的,咱们也声明了其它一些将会使用到的属性。filesCount属性表面一个目录下的文件数。Filename属性被设置为当前选

中的文件的文件名,而且加载/保存文件的内容都存放在属性fileContent中。


 

         Files列表属性是在该目录下过滤后剩下的文件列表。Directory类实现了过滤掉非法的文本文件,仅仅以”.txt”结尾的文件才是

合法的。Qlists能够经过在C++中声明为QQmlListProperty属性在QML文件中使用。模板对象都须要继承自QObject,所以File类也

须要从QObject集成。在Directory类中,File对象列表保存在一个名为m_fileList的QList中。


 

     这些属性能够在QML中做为Directory元素的属性使用。须要注意的是,咱们不须要再C++代码中建立一个表示标签的”id”属性。


 

        由于QML使用了JavaScript的语法和结构,所以咱们能够在文件列表中迭代并获取其属性。要获取第一个文件的名字属性,

咱们可使用”files[0].name”

        普通的C++函数也能够在QML中使用。文件加载和保存函数使用C++代码实现,而且使用Q_INVOKABLE宏声明。可选的

是,咱们能够将这些函数做为槽函数声明,而后这些函数也能够在QML中使用。


 

         Directory类童谣须要在目录内容发生改变的时候通知其它的对象。这个特性可使用信号实现。在前面已经提到过,QML

信号有一个以on开头的信号处理器。这里咱们将信号命名为directoryChanged,在目录被刷新的时候该信号被发射。目录刷新仅

仅是再次加载目录内容,而且更新合法的文件列表。QML元素能够经过链接到onDirectoryChanged信号处理上获得目录被改变

的通知。

        List属性须要继续被讨论。这是由于list属性使用回调函数访问和修改list的内容。List属性的类型是QQmlListProperty<File>。无

论在何时访问列表,访问器(accessorfunction)都应该返回一个QQmlListProperty<File>。模板类型File,须要继承自QObject。因

此要构造QQmlListProperty属性,咱们须要将列表的访问器和修改器的函数指针做为参数传递给构造器。一样咱们须要一个指向

File列表的QList指针。


 

       构造器将指针传递给追加列表的函数,计算列表大小的函数,使用索引(index)获取条目的函数以及清空列表的函数。至于追加

列表的函数是必须的。须要注意的是:函数指针必须和AppendFunctionCountFunctionAtFunction以及ClearFunction相匹配。


 

        为了简化文件对话框,Directory类实现了过滤掉非法的文本文件(不以”.txt”结尾的文件)。若是一个文件不是以”.txt”结尾,那么

在它在文件对话框中就是不可见的。一样,咱们的实现也确保了文件的保存是以”.txt”结尾的。Directory类使用QTextStream类读取

文件并将数据写到文件中的。

        使用咱们的Directory元素,咱们能够将文件组织为列表,咱们能够知道目录下有多少文件,能够获取文件的名称和内容,而且

在目录内容改变的时候获得通知。

         要编译这个插件,咱们须要在filedialog.pro文件上运行qmake命令,而后运行make命令来编译并将插件拷贝到plugins目录。

在QML中导入插件

        Qmlscene工具将与应用程序同一目录下的文件直接导入。咱们也能够经过建立一个qmldir文件,包含咱们须要导入的QML文件

的位置。Qmldir文件也能够存储插件以及其它资源的位置。


 

        咱们刚刚建立的插件是FileDialog,这是在工程文件的TARGET域指定的。编译后的插件存放在plugins目录下。

将FileDialog集成到FileMenu

        咱们的FileMenu须要显示一个FileDialog元素,FileDialog元素包含了一个目录下文件的列表,容许用户经过在列表中点击来选

择文件。咱们一样须要指定save,load,new三个按钮来获取这些动做。FileMenu包含了一个可编辑的文本输入框,容许用户经过键盘

输入文件名。

        Directory元素在FileMenu.qml文件中被使用到,而且它通知FileDialog元素目录的内容获得了更新。这个通知是在信号处理者onDirectoryChanged中处理的。


 

        为了继续保持咱们的应用程序简单,文件对话框将不会显示任何非法文件。


 

        FileDialog元素将会经过读取files列表属性来展现目录的内容。这些文件将会做为GridView元素的模型,GridView将经过代理

将数据元素以网格的形式显示出来。代理主要用于处理模型的显示,咱们的文件对话框仅仅是建立文字处于中心的网格。点击一

个文件名将会致使一个文件名高亮。当notifyRefresh信号被发射,FileDialog对话框就会被通知从新加载目录的内容。


 

        如今咱们的FileMenu能够链接到相应的动做上。saveButton将会把TextEdit上的文本转化为目录的fileContent属性,而后从文本

输入框中获取文件的名称,该按钮会调用saveFile()函数保存文件。loadButton以相似的过程执行。New按钮将会清空TextEdit的内容。

        EditMenu下的按钮会将copy,paste和selectall这些函数与TextEdit链接起来。


 

 完成文本编辑器


 

        该应用程序是一个简单的文本编辑器,能够加载和保存文件,并执行简单的操做:剪切、复制以及全选等功能。

运行文本编辑器

        在运行文本编辑器以前,咱们须要将C++代码编译为插件。要编译C++代码,咱们进入filedialog目录,运行qmake命令,而后

使用make或者nmake编译,这取决于你的平台。接着运行qmlscene打开texteditor.qml文件便可。

       源代码在examples/tutorials/gettingStartedQml目录下。

相关文章
相关标签/搜索