首页 > 代码库 > Qt Quick应用开发介绍 1-5

Qt Quick应用开发介绍 1-5

Qt Quick应用开发介绍 

Introduction to Application Development with Qt Quick Release 1.0


Chapter1 Introduction 介绍

1.1 谁应该阅读这份教程

本教程解释了Qt Quick应用开发的基础以及使用示例代码帮助全面了解; 教程包含标准Qt Quick文档和基础概念, API以及详细的源码信息;

本教程是为了新接触Qt Quick的你准备的, 虽然从基础开始, 但你还是要熟悉编程的概念, 有JavaScript的基础知识更好;

结束本教程之后, 你应该可以写自己的Qt Quick应用, 通过阅读高级文档和分析源码来开始发掘更多的知识;

1.2 journey旅程的目的

本教程会从传统的"Hello World"应用开始, 到一个完整的QtQuick应用结束; 最后的应用程序会覆盖QtQuick编程的各个主要方面;

特性总是会更多的

不要怀疑, 更多的特性会被不断加入, 但是教程不得不在某个有限的程度上结束; 你可以继续了解源码, 扩展程序;

教程就像一个到各个概念点的旅途; 在著名的站点我们会驻足游览, 获得的知识越多, 扩展的方面就越多; 每一步我们都会看些例子, 讨论发生了什么, 如何在我们的应用中使用这些概念; 最后, 你会惊讶程序比起教程的长度来说要简单的多; 我们在这想要的不是快速开发, 而是对整个旅程的充分感受;

在"Hello World"之后, 我们会去开发一些简单应用, 看看怀旧的LED钟; 下一步是在线读取, 分析, 显式天气预报; 迟些, 我们会尝试把这两个应用整合到一起: 一个有LED钟显式的天气预报;

注意, 为了简化, 一些高级的部分在这个教程中没有涉及; 下一章会提到这些; 

1.3 下载

http://qt-project.org/wiki/developer-guides  略

1.4 帮助

Qt Bug Tracker

1.5 相关资料

查询Qt网站Document和Wiki;

1.6 License

Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). All rights reserved

http://creativecommons.org/licenses/by-sa/2.5/legalcode 

---1---


Chapter2 Work Environmeny Setup 工作环境设置

如果这是你第一个QtQuick项目, 看一下这些工具还是有意义的;

2.1 工具安装

建议使用最新的Qt库; www.qt-project.org/downloads 如果已经有了Qt开发环境, 保证使用版本是Qt4.7.4或4.8包含QtQuick1.1;

2.2 创建QtQuick应用

这个教程中会使用QtCreator作为IDE; http://doc-snapshot.qt-project.org/ 

QtCreator创建工程的时候只是创建了工程文件[pro], 同时会少许初始化的代码; wizard中关于QtQuick有两个选择: QtQuick App和QtQuick UI; 它们的主要区别在于程序代码是如何执行的, 这和QtQuick在底层是怎样工作的有关;

QtQuick UI: 你会得到一个qml文件和两个项目文件; .qml文件是代码; .qmlproject文件是项目, 现在不用改动; .qmlproject.user是项目设置, 自动生成, 不用改, 也不用放到VCS(版本控制系统)中;

Ctrl-R执行, 或者 Build->Run; 你会看到在一个窗口上的Hello World的text;

Note 这里没有编译步骤, QtQuick是基于脚本的, 就像Python, Perl; 脚本需要有个引擎来解释和执行; QtQuick的引擎叫Qt Declarative UI Runtime http://qt-project.org/doc/qt-4.8/qmlruntime.html [QDeclarativeEngine, QDeclarativeComponent, QDeclarativeContext] QtQuick程序可以通过两种方式使用引擎:

a) 把qml文件当作命令行选项传给引擎程序: qmlviewer; http://qt-project.org/doc/qt-4.8/qmlviewer.html [QtObject, , runtime.isActiveWindow/orientation] 

b) 把Qt Declarative UI Runtiime整合到C++代码, 然后装载qml文件;

用a)方式, 会使用Qt安装路径bin文件夹下的qmlviewer程序; 它包含了使用Qt Declarative UI Runtime的代码, 在命令行装载qml文件; 在QtQuick UI项目中, QtCreator自动运行qmlviewer来装载main.qml, 使用Ctrl-R或者Run来运行; 不需要编译;

qmlviewer程序也提供了debugging接口和许多方便的工具; 看一下文档或者试试 qmlviewer --help;

这种项目类型便于查看QtQuick的效果; 下一节我们会开始学习QtQuick Application项目类型, 理解怎样在C++中开发标准Qt application;

Qt Quick UI只适用于qml文件, 使用script-based程序环境; 复杂程序逻辑和重量级的处理应该放在C++, 然后把API暴露给QtQuick;

2.3 Qt Quick Application 项目类型

另一个项目类型称为Qt Quick Application, 解放所有QtQuick的功能; 如果你创建了一个项目: hello_qt_quick_app, 你会在C++项目中得到: 

- hello_qt_quick_app*.png和.svg: 不同平台下的桌面图标;

- hello_qt_quick_app*.desktop: 不同平台的桌面描述文件;

- hello_qt_quick_app.pro: Qt项目

- hello_qt_quick_app.pro.user: 本地项目设置, 自动生成;

- main.cpp: 程序main文件, 用来启动你自己用QmlApplicationViewer实现的qmlviewer;

- qml: 放qml文件的文件夹;

- qmlapplicationviewer: 实现QmlApplicationViewer和初始化Qt Declarative UI Runtime的文件夹, main.qml也在这;

你的程序有了自己的qmlviewer模块, 还有Hello World qml; 这是一个Qt C++程序, 提供了基本的qmlviewer和一些非桌面平台的代码; 如果你运行项目, QtCreator会编译和构建程序, 然后运行; QmlApplicationViewer装载和执行QtQuick的代码, 和qmlviewer的方式一样;

QmlApplicationViewer是一个Qt Declarative UI Runtime的实例; 使用这种方法, 有利于将QtQuick和C++整合起来, 还可以用C++创建一个QtQuick的Item; 相对这篇教程, 这是比较高级的技术; 可以阅读Qt Declarative UI Runtime的文档, 还有Extending QML Functionality using C++ http://qt-project.org/doc/qt-4.8/qml-extending.html

2.4 Tracing跟踪

在学习过程中你可能想要跟踪程序代码, 在运行时进行检查; Debugging特性丰富的, 在Debugging QtQuick Projects中文档齐全 http://qt-project.org/doc/qtcreator-2.6/creator-debugging-qml.html;  第一次使用先要设置好Debugging Helpers http://qt-project.org/doc/qtcreator-2.6/creator-debugging-helpers.html

第一步, 你更多地会使用简单的方式; 可以使用console.log()/debug() 或者直接print(), 这些方法由JavaScript提供; 

e.g. mouse click:

1
2
3
4
5
6
7
8
MouseArea {
//...
    onClicked: {
        console.log("I was \"" + parent + "\"!")
        console.log("Bye for now!")
        //...
    }
}

这块代码会打印出日志信息;

下一步

你现在有了开发环境和简单的Hello World项目, 可以控制, 运行和观察; 下一张继续讨论核心概念, 然后试着做难一点的东西;

---2---


Chapter3 Qt Quick Core Pronciples for Application Development 开发核心原理

3.1 QtQuick和Classical传统Qt比较

作为Qt的一部分, QtQuick(Qt User Interface Creation Kit)提供了一个全新的创建UI和开发的方式; 多数情况下QtQuick被使用在non-widget的UI中, 具有丰富的动画, 效果和图形资源; 它把虚拟转化一个图形元素成为一个可交互的UI component的工作量大大减轻;

你可以将草稿很快做成一个prototype; 甚至从草稿代码到继续开发阶段不用重写代码; 可以把图形, 交互和动画设计都包含进开发过程中, 而不用去画PPT或准备PDF的设计图;

QtQuick的开发不需要C++知识; 它是一个脚本语言, 借鉴于CSS和JavaScript; 语法和功能上用了很多JavaScript的; 它使用JavaScript引擎执行代码; 熟悉QtScript的人会觉得很简单; 虽然不需要C++来开发QtQuick, 但是你可以使用C++扩展QtQuick, 创建自己的模块; 它还可以用来传递数据; 

QtQuick不会代替传统Qt

虽然你可以完全只使用QtQuick来开发应用, 传统Qt和C++的角色转换了, 但并不代表不重要了; 在复杂的现实世界程序中, QtQuick主要是给UI和用户交互用的, 程序的业务逻辑和系统接口仍旧是用C++写的;

3.2 Declarative vs imperative programming 

QtQuick可以看作是声明式编程 http://en.wikipedia.org/wiki/Declarative_programming的一种实现; QtQuick程序描述了UI是由哪些item组成, 它们看起来应该是怎样的, 应该对用户行为有怎样的相应; 这和传统的Qt C++的命令式编程 http://en.wikipedia.org/wiki/Imperative_programming 有很大区别, 它把算法和语句都放在了前端; 

这个区别是为什么QtQuick可以直接用来设计UI的主要原因; UI设计和屏幕内容以及用户交互打交道, 假设程序逻辑是在看不到的地方; 需要的话, QtQuick允许使用命令式编程的元素, 你甚至可以用JavaScript写相当复杂的算法;

3.3 四个cornerstone基石

QtQuickk有4个基础

1) UI由嵌套的元素组合, 排列成一个分层次的树形结构;

2) 元素由属性来描述;

3) 一个属性可以绑定到另一个属性上, 两者一直保持相同的值;

4) 每个属性的改变或信号的发送, 会形成一个通知或者被handler处理;

嵌套地一个个增加元素来写一个QtQuick程序, 自定义元素的外观和行为可以通过改变属性来做到; 如果一个元素的属性要跟随另一个元素的属性的值的变化, 可以绑定它们; 如果你要对属性的改变做出反应, 可以添加一些handler代码来自动执行操作;

1
onHeightChanged: print ("new size: ", width, "x", height)

如果你改变窗口的高度, 控制台会输出尺寸信息;

如果这是在传统的text赋值中, 是不会有这种改变, 而且text会保持原始的值; 这是一个很有用的技术, 在QtQuick中会频繁出现;

考虑第四点: 每次属性的改变都会形成一个通知; 我们添加了handler: onHeightChanged; 每次height变化的时候, 就会有log打印到console; 当你想通知其他元素的时候, 还可以发送信号; 一般来说, 第四个基石和传统Qt的属性机制和信号-槽机制类似;

3.4 从概念到实际的程序

概念学习阶段对于QtQuick的程序开发是重要的; UI基于元素, 多数是Rectangle或者类似的东西; 你可以使用属性绑定到通知handler, 实现一个功能系统; 有一个简单的方法来重用和模块化这些功能; 你程序的第一个版本会很快完成, 甚至没有很多应用逻辑; 你可以添加更多应用逻辑, 然后会发现有些东西需要在UI设计上加强; 这种转化在各种平台各种开发框架中都会出现; QtQuick会使得这些转变省下更多时间, 而且更不易错(error-prone) 你只需在开始的时候在设计概念的分解上花点功夫;

接下去开发一个整合天气预报的数字钟; 这个用例程序不仅是装饰类的; 想象一下午夜醒来想要快速查看时间然后继续睡; 如果是在一天的开始, 你有可能想要看看天气预报; 我们的程序显示当前时间和网上抓取的第二天的天气预报; 另外, 我们需要顶层窗口来存储一些基本设置(e.g. 所在城市) 这样就有三个组件: 时钟, 天气预报和设置; 时钟和预报在同一个屏幕, 而设置则是可以弹出和关闭的; 

时钟元素看起来像这样:

 

这个界面显示当前时间和日期, 可以在元素上直接看到; 

天气预报通常显示当天信息和之后几天的预报; 这个信息每天都会重复, 显示天气状况和温度; 我们可以从网络上的到天气数据; 天气元素要和天气数据关联起来, 在选择element的时候要记得这点;  

根元素包含所有天气相关的元素:

时钟和天气部分相对独立, 而且分开开发然后最后组合到完整的程序中的做法也比较好;

设置会作为一个独立窗口弹出:

这个元素可以独立开发; 只需要注意找到传递配置数据和设置到程序核心的方式;

另外, 还需要一些基本的UI特性, 如text input field, check box, 简单的button; Visual外观很重要, 我们会花更多时间来拓展学习用QtQuick强化程序;

下一步

下一章使用QtQuick elements组建UI;

---3---


Chapter 4 Elements as building blocks 元素作为构建基本块

QtQuick程序可以被看作一个分层的树形元素; 这个树在屏幕的动态场景中组建; 所有元素可以被看作对象, 其中的父子关系也可以看作一种继承; 一些元素在屏幕上不可见, 但是仍然可以在底层控制或转化成其他元素; 因此, QtQuick创建的块都有个通用名字: Item; Item是大多数其他item的父类(QtQuick中有21个); 作为父类, QMLItem有许多重要的属性会被其他item继承; 查看一下文档, 我们大多数时候都会用到这些item, 但是我们只有在强调一个item是屏幕上可见的时候才使用element;

可视化的元素可以通过改变属性(如position, size, visiblity, opacity, etc)来控制; 这也可以通过动画animation来做到; 有一些特殊的element可以用来捕获各处的用户输入或者可视化的数据; Qt文档提供了一个group列表: http://qt-project.org/doc/qt-4.8/qml-groups.html 

开发QtQuick的时候, 你应该以element为单元考虑UI; UI的变化是transition, element可以移动, 隐藏甚至改变形状; 这和传统编程很不同, 以前思考的是算法, 花不少的时间来让UI变化; 用QtQuick开发UI更像是在做动画;

4.1 用nested嵌套element来Compose组合一个基本UI

在qml中, 就像其他树形结构, 总是有一个根元素, 包含所有其他的元素; 

1
2
3
4
5
6
7
8
9
Rectangle {
    width: 360
    height: 360
    Text {
        anchors.centerIn: parent
        text: "Hello World! My size is " +
        parent.width + " x " + parent.height + "!"
    }
//...

Rectangle是根元素; Text包含文字; 所有的item当作在一个栈上渲染(render), render次序按照它们在树中次序的排列;

  1. 根Rectangle    2.Text...

我们可以添加更多element, 所有都会加在这个栈中, 从左上端(0,0)开始画出; 这是默认的render位置; 这个默认行为会让例子中的元素重叠在屏幕上; 可以添加anchors来指定位置; 锚(anchoring)允许element按照互相之间的相对关系来调整位置;

4.2 在屏幕上order排列element

你可以通过绝对位置(x,y)或者相对位置来控制元素位置或者排列顺序;

坐标系统从窗口左上角开始, 以真实的像素为单位; 除了(x,y)坐标系, item还有第三个维度, 定义了兄弟item的堆叠顺序; 这个维度用z属性来定义, 默认值是0; 如果你把z设置为1, item会升到下一个层次; 

ordered_elements/ordered_elements.qml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Rectangle {
    width: 100
    height: 100
    color: "grey"
    Rectangle {
        width: 50
        height: 80
        color: "lightgrey"
        // puts this rect in the front.
        // Uncomment next line or set it to -1 and see what happens
        //z: 1
        // this rect will clip the text element
        // Uncomment this line and see what happens
        // clip: true
        Text {
            text: "Sunday, 5 o’clock"
        }
    }
}

把z设置为-1会把item隐藏进父类的背景中;

Note 如果不把修剪clip属性设置为true, text会在父类的边界处被clip掉; clip是Item的属性, 在所有可视化的element中被继承;

4.3 Arrange整理屏幕上的程序元素element

下一步要整理element, 构筑UI; 整理item带出下一个关键点: item的id;

虽然id在QtQuick中是可选的, 但我们在整理item关系的时候一定会用到它; 通常, 你应该考虑尽量把所有的id都加上; 这样大大提高代码的阅读性, 还可以防止奇怪的副作用; 建议对根元素使用一致的id, 比如root; 这可以帮助你跟踪item的使用情况, 并且防止副作用产生;

前面的例子里用到了anchors, 现在仔细瞧瞧它怎样搭出一个时钟;

拿两个Text元素放入root元素; anchors行使用起来就像属性一样, 把anchors行的属性绑定到另一个上; 基本操作就是把一个anchors属性连到另一个上面; 另外, 你还可以设置anchors留白(margin); margin默认是0, 它定义了设置了anchors的items之间的距离; 

1
2
3
anchors.bottom: root.top
anchors.horizontalCenter: parent.horizontalCenter
anchors.margins: 10

我们把timeText连到root的top, margin设置为10像素; dataText设置到root的bottom; 当你运行程序然后调整窗口大小时, 你会看到Text会保持anchors的位置, 留在top或者bottom处, 只是它们之间的空间大小会变化;

1
2
3
4
5
6
MouseArea {
    anchors.fill: root
    onClicked: {
        Qt.quit();
    }
}

MouseArea填充了整个root的表面, 甚至鼠标点击Text的时候也会响应;

Anchors很简单, 但是如果你有很多element的时候还是要注意, 否则你可能丢失element位置方向; 一个有用的方法是anchor到主元素, 然后保证anchor的层次顺序; Detail: http://qt-project.org/doc/qt-4.8/qml-anchor-layout.html 

另一种方式是Positioner: http://qt-project.org/doc/qt-4.8/qml-positioners.html 用来处理一些按常规次序排列的element; [Row, Column, Flow...] 

ex. 可以试着使用positioner, 它可以简化代码, 将两个Text放到Column中; spacing是间距, anchors.centerIn: root可以保持Column在root的中间;

static_clock1/static_clock1.qml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Column {
    id: clockText
    anchors.centerIn: root
    spacing: 20
    Text {
        id: timeText
        anchors.horizontalCenter: parent.horizontalCenter
        text: "13:45"
    }
    Text {
        id: dateText
        anchors.horizontalCenter: parent.horizontalCenter
        text: "23.02.2012"
    }
}

 如果你调整窗口大小, 内容会保持在中间;

4.4 Properties属性

前面一节中我们把各种值绑定或分配给了property, 从而改变Item; property扮演了重要角色, 而且有广泛的使用; 这节制讨论用户案例然后做练习;

1
2
3
4
Rectangle {
    id: myButton
    color: "white"
}

myButton自动包含了所有Rectangle的默认属性, 包括默认值; 实现一个button, 你可能需要添加一些属性, e.g. border color 甚至是一个普通的pen来画label text和border color; 根据应用逻辑来实现其他的item;

根据下面的语法来定义新的属性:

1
[default] property <type> <name>[: defaultValue]

比如一个border color: 

1
property string borderColor: "white"

这里使用了string类型; QML property的基本类型: http://qt-project.org/doc/qt-4.8/qdeclarativebasictypes.html : action, enumeration, list..

有些情况下, 定义一个别名alias可以代替定义新的属性;

1
[default] property alias <name>: <alias reference>

实际上, 在这个例子中, button继承自Rectangle, 我们应该定义一个别名, 因为Rectangle已经有个property来定义border color;

1
2
3
4
Rectangle {
    id: myButton
    property alias borderColor: myButton.border.color
...

default关键字是可选的, 用来创建默认属性; 更多进级用法: http://qt-project.org/doc/qt-4.8/qml-extending.html#default-property & http://qt-project.org/doc/qt-4.8/propertybinding.html#default-properties 

就如前面提到的, 一个property的改变产生notification信号, 会有一个handler来相应property change; handler被分配到属性的 on<property_name>Changed方法, 这些方法是property自动生成的, 包括自定义的property; 

ex: Rectangle的width和height

1
2
onWidthChanged: console.log("Rectangle width: ", width)
onHeightChanged: console.log("Rectangle height: ", height)

如果你resize这个窗口, 你会看到console的输出: width的height的改变;

handler中的代码可以变得更繁复, 可以使用JavaScript; 

property绑定是另一个基础; 它可以使一个property跟随另一个property的改变而改变; 这可以发生在不同的item中, 而且实际上大多数时候是用在不同的item之间的; 绑定发生在每次你使用冒号 : 的时候, 右边的值是可变的;

1
2
id1.text: id2.text // text in the id1 follows changes of the text in id2
width: 16 height/9 // this keeps an item being the 16:9 aspect ratio :-)

你也可以做些计算甚至将一个有返回值的function绑定上去;

property_binding/property_binding.qml

鼠标点击事件被MouseArea接收, 在onClicked hander中可以通过JavaScript进行处理;

1
2
3
property int adaptiveSize: root.width/10
...
font.pixelSize: adaptiveSize

如果resize窗口, font的像素尺寸将会根据root的width/10来变化;


4.5  Other Visual Composition Elements 其他可视化的组合元素

QtQuick1.x提供了宽泛的item选择来创建UI: http://qt-project.org/doc/qt-4.8/qdeclarativeelements.html 其中有4个element能用来组建UI;

- 可视化的element, 如text, rectangle;

- 加载的Loaded内容如image, web page, font;

- 可视化的element, 用各种方式来整理上面元素, 需要的话可以使用带数据的model;

- 效果effect, 比如动画animation和过渡transition;

Qt5增加了两个:

- 矢量图形画布

- 3D渲染OpenGL效果effect和着色shader; 

refer to http://qt-project.org/wiki/Developer-Guides/ 

即使你还没有在列表中看到高级的UI compontent, QtQuick给了你足够多的能力来组合丰富的UI; 这些UI可以像卡通, 图像接收用户输入, 平滑地改变形状, rectangle变成circle, ellipse等等; 你也可以轻松创建经典的UI components; 当你开始做UI的时候, 试着先分解成基础元素, text, image, view; 想想element互相之间是怎么交互的, 用户输入和变化时会发生什么;

下一步

下一章学习怎样加载外部内容, 创建所需的UI样式;

---4---


Chapter5 Loading and Displaying Content 加载和显示内容

加一步要在时钟上加上背景图代替实色solid color, 用不同字体显示时间和日期; 这个内容的样式通常是在外部文件中提供的; 我们不得不学习怎样读取和现实这样的内容; 也要学习怎样自定义元素的标准外观, 来将一个应用的外观实现得更有吸引力;

5.1 Access and load content 访问和读取内容

QtQuick 1.x允许在网络上或者本地文件系统中加载image和font; 可读取内容的相关文件的路径根据QML文件的相对位置来定义; 这相对路径也可以被网络地址代替; 这样把内容从本地移动到网络上就很简单, 不需要代码有很大的改变; detail: http://qt-project.org/doc/qt-4.8/qdeclarativenetwork.html   

读取外部内容可能总是会出问题; 文件方错了, 网络连接太慢或者服务器下线了; ImageFontLoader 提供了statusprogress属性来处理这些情况; progress的值从0.0到1.0变化, 和真实的读取进度保持一致; 如果内容是从文件系统读取的, 而我们没有在程序中使用它, 进度会几乎立即被设为1.0; 读取字体的代码块code segment, 以及跟踪的状态如下:

1
2
3
4
5
6
FontLoader {
    id: ledFont
    source: "./content/resources/font/LED_REAL.TTF"
    onStatusChanged: if (ledFont.status == FontLoader.Error)
                        console.log ("Font \"" + source +"\" cannot be loaded")
}

我们的新font, LED_REAL.TTF, 保存在content文件夹, 和程序在相同的位置; 如果由于某些原因无法加载, console会打印出错误信息, 程序会继续使用默认font;

5.2 Basic Image Parameters 基本的图像参数

加载Image的方式和Font一样:

1
2
3
4
5
6
7
Image {
    id: background
    source: "./content/resources/light_background.png"
    fillMode: "Tile"
    anchors.fill: parent
    onStatusChanged: if (background.status == Image.Error) console.log ("Background image \"" + source + "\" cannot be loaded")
}

这里需要改变一些图像的属性; image要覆盖整个顶层元素(parent)的表面; 很多情况下, 会使用用带图案pattern的小图片填充一个背景; 缩放scale图片的大小让它适应背景尺寸会改变pattern, 背景就会和设想的不一样; 这样的情况下, 你可以设置fillMode为Tile;

处理Image的尺寸

图片的大多数可视化属性可以通过父类(Item)的属性来改变; 其他Image的属性帮助处理关键的Image的样子--size; 如果你要处理大图片, 你应该设置sourceSize, 设置成你真正需要的尺寸, 否则图像将以全尺寸加载; 注意paintedHeightheight的区别, 还有paintedWidth和wdith; painted属性描述了图片在画到屏幕上时占据的区域大小, 而普通的h/w属性描述了图像加载的尺寸; 如果图片被scale过, 这两者的大小可能都不同; 如果你把从Item继承而来的scale属性改变了, 要注意fillMode对真实的scale结果上的影响; smooth属性可以将缩放过的图像边缘平滑, 但是也会引来性能损耗performance cost; 

5.3 Basic Text Parameters 基本的文本参数

第一节中我们读取了一个自定义的 LED-like字体; 现在要将它分配给相应的text元素; Text有一组font属性; 它被用来自定义给中字体相关的text属性; 其中font.family持有font的名字;

找到安装的字体

有时要找到你系统中有哪些字体被安装, 它们的名字是什么, 是很麻烦的事情; 这里有个例子: http://qt-project.org/doc/qt-4.8/declarative-text-fonts-fonts-qml-fonts-qml-availablefonts-qml.html 

text的其他属性允许text外观上的各种改变; 在我们的例子中, 使用color, style和size相关的属性;

自定义的text元素看起来像这样:

1
2
3
4
5
6
7
8
9
10
Text {
    id: timeText
    text: root.currentTime
    font.pixelSize: root.height //root.timeTextProportion
    font.family: ledFont.name
    font.bold: true
    color: root.textColor
    style: Text.Raised
    styleColor: "black"
}

计划是将实现变得尽量灵活, 对于所有element的size和布局layout在不同的屏幕尺寸上运行都能适应; 因此上面的代码将pixelSize绑定到了root的height上; 这样text会跟随root的height而缩放; 这里还有方法去做得更好, 但是这个版本的QtQuick没有提供font metrics(度量单位)数据; 如果有font metric的话, 我们可以让text的size自适应width的变化 [C++可以通过QFontMetrics做到] 

为了让timeText更好看点, 我们用了点小技巧, 把style设置为Text.Raised, styleColor设为"black"; 这让text从背景中分离开, 看起来好像悬浮在上面一样;

Text还提供了基本的布局控制(e.g. 你可以设置wrapMode) 最主要的事情是要记住text的格式, Text支持rich text的修饰; 这使得一块text中的不同部分可以用各种不同的格式来显示, 包括color, size, etc;

5.4 Get ready for translation 翻译

开发程序的时候, 基本都要考虑考虑国际化版本, 即使你暂时还没有计划; Qt提供了一系列根据来给QtQuick使用; 如果你一开始就知道这些必须的工具, 那么在你的代码变多, 程序变成复杂的系统的时候可以帮你节省很多时间; 

QtQuick提供的翻译相关的API基本和Qt Script一样; http://qt-project.org/doc/qt-4.8/scripting.html#produce-translations [qsTr(), qsTranslate() and the QT_TR*_NOOP()] 主要的API是qsTr()方法, 应该在程序所有可见的string上都包装这个方法;  

ex. hello world

1
2
3
4
Text {
    anchors.centerIn: parent
    text: qsTr("Hello World")
}

程序将和使用qsTr()之前一样允许; 你需要使用Qt translation工具链来让翻译起效; 参考http://qt-project.org/doc/qt-4.8/qdeclarativei18n.html , 了解怎样生成和整合翻译文件; 当翻译文件准备好了, 有3个方式来加载它们:

- 通过使用qmlviewer命令行选项 -translate

- 将文件放到 i18n子目录(http://qt-project.org/doc/qt-4.8/declarative-i18n.html ); [lupdate linguist  lrelease]

- 通过改变qmlviewer的默认行为, 用自己的方式来加载QML和翻译文件(超出本文范围)

如果你想要做一个right-to-left的程序版本, e.g. Arabic, 查看 QML Right-to-left 用户接口 http://qt-project.org/doc/qt-4.8/qml-righttoleft.html 

运行时切换语言

现在还没有标准的API可以在QtQuick程序开始后加载新的语言; 但还是可以使用一些其他的代码;  http://qt-project.org/wiki/How_to_do_dynamic_translation_in_QML/ [利用空字符串emit textChanged消息]

更多关于internationalization的细节:

- Qt文档: http://qt-project.org/doc/qt-4.8/i18n-source-translation.html 

- Qt文档: http://qt-project.org/doc/qt-4.8/internationalization.html 

- Qt开发者Wiki: http://qt-project.org/wiki/QtInternationalization [tr() 和 toUtf8()]

5.5 Static Clock Application Code 静态的时钟程序代码

static_clock2/static_clock2.qml

下一步

下一章关于QtQuick里的脚本script; 用一个小脚本让时钟走起来; 

---5---

---YCR---