教程将介绍使用Qt5.x版本开发应用程序的相关技术。教程更侧重讲解新的Qt Quick开发技巧,在讲解Qt Quick扩展内容时会涉及部分Qt C++内容。
本章是对Qt5的概述,通过一个Qt5的应用程序示例展示Qt5中一种新的开发模式。此外,本章旨在全面概述Qt5,以及如何与Qt5的开发者取得联系。
1.1 序
Qt历史
Qt4自2005年发布已为成千上万的应用程序甚至桌面操作系统、移动操作系统提供了稳定、可靠的开发框架。计算机用户的使用模式近年发生了变化,用户正在从传统PC转向笔记本电脑或智能手机。传统PC被越来越多的触摸屏设备取代,计算机的用户体验模型也在跟随改变。在这之前Windows UI占据了我们的世界,但现在我们会花更多的时间使用其它的UI语言开发便携式设备用户界面。
Qt4的设计用于满足开发者在主流桌面操作系统上有一套表现一致的窗口组件可以使用。如今Qt的使用者面临了新的问题,他们需要提供可触碰交互的用户界面以满足软件界面需求,并在主流桌面操作系统和移动操作系统上实现这些界面。从Qt4.7版本开始引进了Qt Quick,它让Qt的使用者可以用简单的元素对象创建一套界面组件,并通过组合界面组件的方式来完成软件界面需求。
1.1.1 Qt5与Qt4
Qt5是Qt4版本完整的更新。自Qt4.8版本发布,Qt4已经发布了7年,现在这个工具将会更加令人惊奇。
Qt5主要特性:
出色的图形能力:Qt Quick2基于OpenGL(ES)场景实现,重写的图形堆栈让开发者可以轻松实现图形特效。
高效的开发模式:使用QML和JavaScript创建用户界面,后端使用C++处理数据。前后端的分离让前端开发人员可以快速迭代并专注于用户界面开发,后端的C++开发人员则专注于软件的稳定性、高性能和扩展能力。
跨平台能力:基于Qt平台的统一抽象实现,能够方便地将Qt移植到大多数操作系统平台。Qt5由基础模块和附加模块组成,操作系统开发者只需移植基础模块就可以保证Qt最小运行环境。
开源:Qt是由qt.io主导的开源项目,由社区驱动开发。
1.2 Qt5介绍
1.2.1 Qt Quick
Qt Quick是Qt5界面开发技术的统称,是以下几种技术的集合:
QML - 界面标记语言
JavaScript - 动态脚本语言
Qt C++ - 跨平台C++封装库
QML是与HTML类似的一种标记语言。在QtQuick中将由标签组成的元素封装在大括号中Item{}
。这样的设计重新定义了界面的创建方式,对于开发者而言更加简单易读。可以使用JavaScript开发界面功能,也可以使用本地Qt C++函数接口扩展界面功能。简单来说,声明式的UI被称作前端,本地C++部分称作后端,将复杂的计算过程与本地设备操作从界面开发中分离。
在一个典型的Qt5项目中,前端采用QML/JaveScript开发界面,后端采用Qt C++与系统交互并完成复杂的运算逻辑,将侧重设计的界面开发与功能开发的工作内容分离。通常后端开发者可以使用Qt的单元测试框架完成单元测试后将函数接口提供给前端开发者使用。
1.2.2 Qt5用户界面开发示例
我们将使用QtQuick创建一个简单的界面,这个例子展示了QML语言的一些特性,在例子完成后我们将获得一个可以旋转的风车。
我们开始创建一个空的main.qml
文档。QML文件采用.qml
作为文件格式后缀。作为一种标记语言(类似HTML)一个QML文档有且只有一个根元素,在这个例子中使用Image
元素作为根元素,这个元素的宽度、高度与"images/background.png"
图像相同。
import QtQuick 2.5
Image {
id: root
source: "images/background.png"
}
QML中不限制根元素类型,在上面这段代码中我们设置了Image
元素的source
属性作为我们的背景图像,它也是我们的根元素。
注意
每个元素都有属性,比如Image
有width
和height
,也会有其它的属性如source
。Image
元素的尺寸会自动与source
设置的图像匹配。想要自定义Image
元素的尺寸必须显式的定义width
和height
的值。
大多数标准元素都在QtQuick
模块中,通常我们在导入声明中首先包含这个模块。
id
是个特殊的属性,它可以作为一个标识符在当前文档内引用对应的元素。注意:id
被定义后无法再改变,在程序执行期间也无法被赋值。使用root
作为根元素id仅仅是作者的习惯,这样可以在复杂的QML文档中快速引用最顶层元素。
我们使用分离的风车竿和风车的图片作为前景元素。
风车竿需要放置在背景的水平居中位置,并且竿的底部与背景底部平行。风车需要放置在背景中央位置。
通常用户界面由不同的类型的元素组成,而不是像这个示例只有图像。
Image {
id: root
...
Image {
id: pole
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
source: "images/pole.png"
}
Image {
id: wheel
anchors.centerIn: parent
source: "images/pinwheel.png"
}
...
}
为了将风车放在中央,我们需要使用一个较复杂的属性anchor
。锚点可以指定对象与父对象和同级对象的相对几何位置,比如定义元素放在另一个元素的中央(anchors.centerIn: parent)
。锚点定义时两端都可以定义元素的左侧(left)、右侧(right)、顶部(top)、底部(bottom)、居中(centerIn)、填充(fill)、垂直居中(verticalCenter )和水平居中(horizontalCenter )相对位置。当然它们必须是可以匹配,无法定义一个元素的左侧与另一个元素的顶部对齐。
这样我就能设置风车的位置在我们背景元素的中央了。
—here—-
注意
有时你需要进行一些微小的调整。使用anchors.horizontalCenterOffset或者anchors.verticalCenterOffset可以帮你实现这个功能。类似的调整属性也可以用于其他所有的锚。查阅Qt的帮助文档可以知道完整的锚属性列表。
注意
将一个图像作为根矩形元素的子元素放置展示了一种声明式语言的重要概念。你描述了用户界面的层和分组的顺序,最顶部的一层(根矩形框)先绘制,然后子层按照包含它的元素局部坐标绘制在包含它的元素上。
为了让我们的展示更加有趣一点,我们应该让程序有一些交互功能。当用户点击场景上某个位置时,让我们的风车转动起来。
我们使用mouseArea元素,并且让它与我们的根元素大小一样。
Image {
id: root
...
MouseArea {
anchors.fill: parent
onClicked: wheel.rotation += 90
}
...
}
当用户点击覆盖区域时,鼠标区域会发出一个信号。你可以重写onClicked函数来链接这个信号。在这个案例中引用了风车的图像并且让他旋转增加90度。
注意
对于每个工作的信号,命名方式都是on + SignalName的标题。当属性的值发生改变时也会发出一个信号。它们的命名方式是:on + PropertyName + Chagned。
如果一个宽度(width)属性改变了,你可以使用onWidthChanged: print(width)来得到这个监控这个新的宽度值。
现在风车将会旋转,但是还不够流畅。风车的旋转角度属性被直接改变了。我们应该怎样让90度的旋转可以持续一段时间呢。现在是动画效果发挥作用的时候了。一个动画定义了一个属性的在一段时间内的变化过程。为了实现这个效果,我们使用一个动画类型叫做属性行为。这个行为指定了一个动画来定义属性的每一次改变并赋值给属性。每次属性改变,动画都会运行。这是QML中声明动画的几种方式中的一种方式。
Image {
id: root
Image {
id: wheel
Behavior on rotation {
NumberAnimation {
duration: 250
}
}
}
}
现在每当风车旋转角度发生改变时都会使用NumberAnimation来实现250毫秒的旋转动画效果。每一次90度的转变都需要花费250ms。
现在风车看起来好多了,我希望以上这些能够让你能够对Qt Quick编程有一些了解。
1.3 Qt构建模块(Qt Building Blocks)
Qt5是由大量的模块组成的。一个模块通常情况下是一个库,提供给开发者使用。一些模块是强制性用来支持Qt平台的,它们分成一组叫做Qt基础模块。许多模块是可选的,它们分成一组叫做Qt附加模块,预计大多数得到开发人员将不会使用它们,但是最好知道它们可以对一些通用的问题提供非常有价值的解决方案。
1.3.1 Qt模块(Qt Modules)
Qt基础模块是对Qt一台的必要支持。它们使用Qt Quick 2开发Qt 5应用程序的基础。
核心基础模块
以下这些是启动QML程序最小的模块集合。
模块名 | 描述 |
---|---|
Qt Core | 核心的非图形类,供其它模块使用。 |
Qt GUI | 图形用户界面(GUI)组件的基类,包括OpenGL。 |
Qt Multimedia | 音频,视频,电台,摄像头的功能类。 |
Qt Network | 简化方便的网络编程的类。 |
Qt QML | QML类与JavaScript语言的支持。 |
Qt Quick | 可高度动态构建的自定义应用程序用户界面框架。 |
Qt SQL | 集成SQL数据库类。 |
Qt Test | Qt应用程序与库的单元测试类。 |
Qt WebKit | 集成WebKit2的基础实现并且提供了新的QML应用程序接口。在附件模块中查看Qt WebKit Widgets可以获取更多的信息。 |
Qt WebKit Widgets | Widgets 来自Qt4中集成WebKit1的窗口基础类。 |
Qt Widgets | 扩展Qt GUI模块的C++窗口类。 |
Qt附加模块
除了必不可少的基础模块,Qt提供了附加模块供软件开发者使用,这部分不一定包含在发布的版本中。以下简短的列出了一些可用的附加模块列表。
Qt 3D - 一组使3D编程更加方便的应用程序接口和声明。
Qt Bluetooth - 在多平台上使用无线蓝牙技术的C++和QML应用程序接口。
Qt Contacts - 提供访问联系人与联系人数据库的C++和QML应用程序接口。
Qt Location - 提供了定位,地图,导航和位置搜索的C++与QML接口。使用NMEA在后端进行定位。(NMEA缩写,同时也是数据传输标准工业协会,在这里,实际上应为NMEA 0183。它是一套定义接收机输出的标准信息,有几种不同的格式,每种都是独立相关的ASCII格式,逗点隔开数据流,数据流长度从30-100字符不等,通常以每秒间隔选择输出,最常用的格式为”GGA”,它包含了定位时间,纬度,经度,高度,定位所用的卫星数,DOP值,差分状态和校正时段等,其他的有速度,跟踪,日期等。NMEA实际上已成为所有的GPS接收机和最通用的数据输出格式,同时它也被用于与GPS接收机接口的大多数的软件包里。)
Qt Organizer - 提供了组织事件(任务清单,事件等等)的C++和QML应用程序接口。
Qt Publish and SubScribe - Qt发布与订阅
Qt Sensors - 访问传感器的QML与C++接口。
Qt Service Framework - 允许应用程序读取,操纵和订阅来改变通知信息。
Qt System Info - 发布系统相关的信息和功能。
Qt Versit - 支持电子名片与日历数据格式(iCalendar)。(iCalendar是“日历数据交换”的标准(RFC 2445)。 此标准有时指的是“iCal”,即苹果公司的出品的一款同名日历软件,这个软件也是此标准的一种实现方式。)
Qt Wayland - 只用于Linux系统。包含了Qt合成器应用程序接口(server),和Wayland平台插件(clients)。
Qt Feedback - 反馈用户的触摸和声音操作。
Qt JSON DB - 对于Qt的一个不使用SQL对象存储。
注意
这些模块一部分还没有发布,这依赖于有多少贡献者,并且它们能够获得更好的测试。
1.3.2 支持的平台(Supported Platforms)
Qt支持各种不同的平台。大多数主流的桌面与嵌入式平台都能够支持。通过Qt应用程序抽象,现在可以更容易的将Qt移植到你自己的平台上。在一个平台上测试Qt5是非常花费时间的。选择测试的平台子集可以参考qt-project构件的平台设置。这些平台需要完全通过系统的测试才能确保最好的质量。友情提醒:任何代码都可能会有Bug的。
1.4 Qt项目(Qt Project)
来自qt-project百科:Qt-Project是由Qt社区上对Qt感兴趣的人达成共识的地方。任何人都可以在社区上分享它感兴趣的东西,参与它的开发,并且向Qt的开发做出贡献。
Qt-Project是一个为Qt未来开发开源部分的组织。它基于使用者的贡献。最大的贡献者是DIGIA,它可以提供Qt的商业授权。
Qt对于公司分为开源方向和商业方向。商业方向的公司不需要遵守开源协议。没有商业方向的许可的公司不能使用Qt,并且它也不允许DIGIA向Qt项目贡献太多的代码。
在全球有很多公司,他们在不同的平台上使用Qt开发产品,提供咨询。同样也有很多开源项目和开源开发者,它们使用Qt作为它们的开发库。成为这样开发活泼的社区的一部分,并且使用这个很棒的工具盒库让人感觉很好。它能让你成为一个更好的人吗?也许:-)。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 2291184112@qq.com