说明:本文档翻译自官方文档,原文参照:Introduction to Qt Quick - Qt Wiki
今天的消费者和企业用户变得难以取悦。伴随着他们成长的是,使用流畅的游戏控制台,以及在电影中看到到更精致的界面。规格和功能列表再也不是买点;它们只是实现目的的手段。视觉冲击和超酷感官体验才是当今紧要的东西,并且消费者希望获取视觉愉悦,不管他们是在使用强大的企业版笔记本电脑,一台移动设备,一个时尚的平板电脑,或是一台机顶盒。
要提供这种体验就需要设计师和开发者进行前所未有的携手合作。设计师把像素图挂在墙上以期望开发者去实现他们的愿景的时代已经一去不复返了。同样,开发者再也不能像以前那样,编码时只考虑性能而不顾及视觉吸引力。设计师、开发者、设计人员必须形成迭代循环,而不是线性依次推进工作。众所周知,QT框架的高运行性能和小空间占用,使它适用于手机、嵌入式和上网本应用。Qt4.7版本新增QML,作为一种声明式语言,它可以按照设计师思考方式编码,并且可以编写作为应用构建模块的Qt Quick元素的声明式语言。每个故事图板的窗口都是元素树上的分支,每个窗口的外观特征都被声明为分支上元素的一个属性;窗口之间的跳转可以使用各种动画和效果渲染。
Qt Quick运行时实现了UI并且提供对本地接口的直接访问,并在适当的情况下使用C++扩展来提升性能。因为运行时在Qt中实现,所以它提供了丰富和灵活的交叉编译。
Qt Creator,一个为了设计师和开发者之间的协同而创建的开发环境,支持Qt Quick。设计师工作在可视环境,开发者工作在全功能IDE,并且Qt Creator支持从设计到编码再到测试再返回到设计的往返迭代。
Qt是为当今产品团队的工作方式创建的。核心业务逻辑由开发者编码并优化性能,界面由使用可视化工具的设计师精心设计,而集成工具支持不同工作领域之间的往返迭代。
概览
Qt的新界面技术由这几部分构成:QML语言、提供基本语言构成的元素、为QML语言提供一个运行时的QtDeclarative(C++)模块、一个基于JavaScript的允许开发者不必使用C++代码就能在他们的工程中实现逻辑的脚本语言。这个技术集由Qt Creator工具提供支持,工具中包括一个可视化设计器和其他支持创建、测试、调试、和优化工程的其他扩展。
QML提供了通过使用元素以声明方式构建对象树的机制。QML改进了JavaScript和Qt即存的基于QObject的类型系统两者之间的集成,增加了对自动动属性绑定的支持,并提供语言级别的网络透明性。元素是由图形和行为构建要素组成的一个复杂工具集。现在QML语言中有超过80种元素,包括可视化元素比如Rectangle(矩形)、Gradient(渐变)和AnimatedImage(动画);交互元素比如MouseArea和Flickable;状态元素包括PropertyChanges and StateChangeScript;过度元素包括Transition和 SequentialAnimation。还有其他元素用来提交数据、查看、定位、以及其他不使用C++代码来构建流畅界面的复杂类元素。
各种元素在QML文档中组合在一起构建各种各样的组件,从简单的按钮和滑块,到完整的支持互联网的应用比如Flicker照片浏览器。
开发者和设计师们都可以自由的创建他们自己的组件,或者从预构建的组件库中选择已有的组件。
Qt Quick建立在现有Qt的长处之上。QML可以用来增量扩展现有的应用或者创建全新应用。QML完全从C++扩展而来。
QML简介
QML是一种丰富的语言,一个全面的介绍超出了本文的范围。本文会介绍QML可以做什么以及如何将QML与C++集成以便在这个两方面达到最好效果:用C++实现的高性能业务逻辑和使用QML的高动态用户界面。在线文档中QML的完整介绍。
QML语言
QML是一种声明式语言,被设计用来绘制用户界面:包括外观和行为。在QML中,用户界面被指定为带有属性的对象树。JavaScript在QML中作为一种脚本语言来使用。
代码片段1展示了基本的QML语法。第一行声明引入QtQuick模块的1.1版本,该版本实现了供应用运行的运行时环境。为了防止后续高版本中引入的元素影响现有文档中的元素,一个文档中可用的元素类型由引入的模块模块控制。这种版本控制允许开发者管理兼容性。
此代码段创建了两个对象:一个Rectangle对象和它的子Image对象。对象由类型指定,紧随其后的一对大括号,大括号之间可以定义对象的附加数据,比如对象的属性值和任意的子对象。
属性通过【属性:值】语法来指定。注意Image对象有一个名为source的属性,该属性已经被绑定值"pics/logo.png"。属性和值通过冒号隔开。
QML中注释类似在C++中类似:
1 单行注释以//开始,在行尾结束
2 多行注释以/*开始,以*/结束
import QtQuick 1.1
Rectangle {
width: 200 // this is an inline comment
height: 200
color: "blue"
/*
And this is a
Multi-line comment.
*/
Image {
source: "pics/logo.png"
anchors.centerIn: parent
}
}
代码片段1:基础QML语法
在对象中,使用【属性:表达式】 语句给属性绑定值。这个语句有两方面的说明。
首先,表达式是一个JavaScript表达式,意味着你可以使用一个计算式、条件判断、或者其他复杂的JavaScript操作来设置属性。
在大多数可以使用常量的地方都可以使用JavaScript表达式。比如,代码片段2用JavaScript表达式的结果给一个矩形的宽度和高度赋值。当然这个简单的表达式并不比在代码1中的敞亮更有用,但是这个功能允许你使用父元素的某个部分的长度给矩形的长度绑定值。
其次,绑定不同与赋值。在赋值中,属性的值是在赋值语句执行时设置,并且之后是固定不变的,除非语句被再次执行。在绑定中,一个属性是在被绑定语句第一次被执行时设置,但是会发生变化在设置属性的表达式结果发生变化时。(如果需要,你可以在JavaScript代码块中使用【属性=表达式】来给一个属性赋值)
技术笔记:属性绑定是通过一个通知信号来实现,通知信号在继承QObject的类中使用Q_PROPERTY() 宏从一个Qt C++对象中声明。如果你不知道它的意思,不要担心。如果你计划纯粹使用QML构建你的应用,那么你不需要理解这一点,因为它仅仅是Qt Quick提供给你的部分底层代码。如果你计划包含一些C++在你的应用中,团队中的Qt C++开发者会知道什么意思。
import QtQuick 1.1
Rectangle {
width: 2 * 100
height: 40 * 5
color: "blue"
Image {
source: "pics/logo.png"
anchors.centerIn: parent
}
}
代码片段2:JavaScript表达式
完整的QML语言支持对象标识符、类型安全属性、信号处理程序、以及大量我们不想让你在此分心的其他细节。如果你准备好了解这类细节,请查看QML语言介绍。
QML元素
一旦你理解了QML语言的基本基础,就是时候去深入了解该技术的主体:元素。元素是用来构建QML程序基本构建模块的模板。QML支持诸如Rectangle和Text等可视元素,MouseArea和Flipable等交互元素,以及RotationAnimation和Transition等动画元素。此外还有其他复杂元素,允许开发者处理数据,在模型-视图体系结构中实现页面,以及其他在这一点上只会增加混乱的默认的组件类型。
所有的元素都包含一个或多个可以由开发者控制的属性(比如color),另外,许多属性包含信号处理器(比如onClicked),可以用来对事件和状态变化做出反应。
可视元素:Hello World
我们已经取得巨大进步,除了在随大溜展示Hello World示例这件事上。这段代码在一个简单的背景矩形上放置一个Hello World!文本:
import QtQuick 1.1
Rectangle {
width: 300
height: 200
Text {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: "Hello World"
}
}
代码片段3:Hello World
让我们来研究下这段代码。片段3中Hello World示例是个QML文档,意味着这是个完整的代码段,是可以运行的。QML文档通常对应于存储在硬盘或者网络资源上的纯文本文件,但也可以直接从文本数据构建。
一个QML文档总是是以一个或者多个import语句开头。这里你可以看到Qt Quick 1.1的引入。
接下来可以看到一个用来创建活动对象的Rectangle元素模板。对象可以包含其他对象,从来创建父子关系。在上述代码中,Rectangle对象是Text对象的父级。Rectangle元素也定义了一个顶级窗口来管理整个UI的视觉边界和这个焦点分割。
技术说明:元素的children属性包含一个所有元素所有可视化子对象的列表;resource属性包含一个所有非可视化对象的等效列表。这个两个列表都是默认隐式添加的,或者如果方便也可以显式添加它们。第三个属性,data,是一个列表,包含在children和resources列表中的对象。你可以显式添加data属性,在需要迭代遍历可视或者非可视对象时会有用处。
所以可以这样写:
Item {
Text {}
Rectangle {}
Timer {}
}
替换掉:
Item {
children: [ //default property and implicitly assigned
Text {},
Rectangle {}
]
resources: [ //default property and implicitly assigned
Timer {}
]
}
anchors.horizontalCenter: parent.horizontalCenter语句将文本的中心与父级矩形的中心对齐。锚点提供了一个途径,通过指定元素与它的父级或者同级元素的关系来定位元素。(注意-如果查看下Rectangle元素的在线文档,会看不到anchors.horizontalCenter 元素。仔细看就会发现Rectangle元素继承了Qt Quick Item元素的所有属性;Item元素提供了anchors.horizontalCenter属性。)
当前有17个锚点元素可用,可以用来对齐、居中、填充元素间隔并设置边距和偏移。比如,代码片段4展示了一个文本元素,定位到一个图片元素的水平中心和垂直方向下方,还带有一个边距。
Image { id: pic; … }
Text {
id: label
anchors.horizontalCenter: pic.horizontalCenter
anchors.top: pic.bottom
anchors.topMargin: 5
…
}
代码片段4:使用锚点对齐元素
分层可视元素
可视元素可以通过透明的方式叠加在一起,透明使用opacity : real 语法,real值取值范围为0 (透明) to 1 (不透明).因为性能原因应谨慎使用,尤其是在动画中,因为每运行一帧动画,各个分层都要渲染。这可能适用于快速原型开发,但是在最终部署前,最好预渲染尽可能多的场景,然后在运行时简单加载像素图像即可。
代码片段5制作了两个偏移并且重叠的两个矩形,一个红色一个蓝色,因为使用了透明度重叠的正方形部分显示紫色。注意子矩形(蓝色)是如何从父级矩形(红色)继承50%不透明度设置的。
Rectangle {
id: parentRectangle
opacity: 0.5
color: "red"
width: 100; height: 100
Rectangle {
id: childRectangle
color: "blue"
x: 50; y: 50; width: 100; height: 100
}
}
代码片段5:谨慎使用透明度
译者注:效果参照如下图片
技术说明:继承元素总是继承它们的基元素属性。比如一个Rectangle也是一个Item,所以Item的所有属性都会存在于Rectangle元素中。因为QGraphicsView的工作方式,子对象有时会继承父级的属性。这意味着当你在一个元素中嵌入其他元素时某些属性会作用到它的子对象。比如代码5中子矩形元素受到父级矩形元素50%不透明度的影响。类似的,如果父矩形被旋转,那么子矩形保持和父矩形的角度关系不变,但是是相对于所在的场景做旋转。
交互元素:鼠标和触摸
为了增加鼠标或者触摸交互需要添加一个MouseArea对象。MouseArea对象可以让用户点击或者拖拽鼠标(或者触摸点)。其他可用的交互元素包括Flickable、Flipable、FocusScope。
注意MouseArea对象可以从任何可视对象分离,这为设计者提供了灵活性。比如,创建一个用户可以点击的按钮,然后使用一个更大区域的鼠标点击区域包围这个按钮,这样就可以允许用户点击时偏离按钮一些像素。
为了在Hello World示例中引入鼠标区域,矩形中包含了一个文本,该文本是一个用来定义鼠标区域的新矩形的子元素。
import Qt 4.7
Rectangle {
color: "#ff0000"
width: 310
height: 210
MouseArea {
anchors.fill: parent
onClicked: {
if(parent.color == "#ff0000") {
parent.color = "#ff9900";
} else {
parent.color = "#ff0000";
}
}
}
Rectangle {
width: 300
height: 200
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
Text {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: "Hello World"
}
}
}
代码片段6:鼠标-触摸交互