1 简介
1.1 QML
- QML(Qt Meta-Object Language,Qt元对象语言)是一种用于描述应用程序用户界面的声明式编程语言。它使用一些可视组件,通过这些组件之间的交互来描述用户界面。QML是一种高可读性的语言,可以使组件以动态方式进行交互,并且易于复用和自定义。
- QML允许开发者和设计者进行联合创作,快速创建高性能的、具有流畅的动画效果的、极具视觉吸引力的应用程序。QML提供了一个具有高可读性的类似 JSON 的声明式语法,并提供了必要的 JavaScript 语句和动态属性绑定的支持。
在Qt 5中,QML语言和引擎框架由Qt QML模块提供。
1.2 Quick
- 一种高级用户界面技术,可以轻松创建供移动和嵌入式设备使用的动态触摸式界面和轻量级应用程序。Qt Quick主要由一个改进的Qt Creator IDE(其中包含了Qt Quick设计器)、新增的简单易学的QML语言和新加入Qt库中名为QtDeclarative的模块等三部分组成。这些使得QML更方便不熟悉C++的开发人员和设计人员使用。
- 在Qt 5中,Qt Quick被描述为QML类库:Qt Quick是QML的一个数据类型和功能的标准库,包含了可视化类型、交互类型、动画、模型和视图、粒子特效和渲染特效等。在QML应用程序中,可以通过一个简单的import语句来使用该模块提供的所有功能。
1.3 优缺点
1.3.1 优点
- 开发高效,简单
1.3.2 缺点
参与的开发技术人员较少,资料不多
2 编码规范
QML是声明式语言,一个用户界面本质是一个树形的对象模型,包含对象属性,组件的依赖关系(从根组件开始)。
统一的代码风格,减少代码冗余,增强其代码可读性,还可以提升工作效率,让程序更清晰、健壮。
2.1 入门样式代码
- 不含JavaScript
Item {
id:root
width:800
height:480
Rectangle {
x:200
y: 60
width:200
height:160
color:“red”
visible: false
}
- 含JavaScript,组件的属性可以直接赋值,也可通过JavaScript代码赋值
Item {
id:root
width:800
height:480
property bool visibleState: false
property bool lightState: false
Rectangle {
x: parent.widht/4
y: parent.height/8
width:parent.widht/4
height:parent.height/3
color:root.lightState ? “red” : "green"
visible: root.visibleState ? true : false
}
}
2.2 文件命名
这里的文件分为 *.qml 文件和 *.js 文件。
2.2.1 QML文件
- 作为程序入口的QML文件,文件名的首字母可以大写,也可以小写,作为Component(控件,类)来使用,首字母必须大写。
- 为了方便qml文件的维护,qml文件的命名规则为:
仅由英文字母组成,以大写字母开始,遵循大驼峰的命名规则,例如:
SwithcButton.qml
MainForm.qml
2.2.2 js文件命名
js文件名由小写的英文字母和_组成。
js文件名一律以“ impl ”结尾,例如:
datetime_helper_impl.js
这样便于在qml中导入*.js_ 文件时,方便命名别名。
2.3 import
import的意思是导入模块,类似 java 和 python 语言中的 import 包,用来导入qml文件所要用到的内置模块、自定义插件、控件、js文件等。
在C/C++中是直接include头文件,将enum,结构体等变量和和函数方法引入,便于程序使用。
2.3.1 import模块的顺序
- 导入 Qt 内置模块
- 导入框架自定义 Qt Quick 模块
- 导入项目自定义 Qt Quick 模块
- 导入本地 *.qml 组件包
- javascript 导入脚本文件
- javascript 引用脚本模块
// MainModule.qml
import QtQuick 2.6
import QtQuick.Controls 2.1
import net.phoneyou.EasyUI 1.0 as HUI
import net.phoneyou.EasyUI.Material 1.0 as HUIMaterial
import net.phoneyou.Roshan.MapRender 1.0 as MapRender2D
import your_project_name 1.0
import "path_to_package"
import "my_component_impl.js" as MyComponent
.import "utils.js" as Utils
2.3.2 "as"规则说明
为了避免不同模块之间的命名冲突,我们在导入模块时可以使用“as”关键字设置该模块在本 qml 文件中的“别名”。
为了保证 Qt 内部组件和命名空间不被污染以及保持代码可以顺利升级–比如升级 Qt 版本,需要确保不对 Qt 模块设置别名,而对其他,比如HUI、Roshan以及其他三方的或者项目内的模块,进行“别名”处理。尤其是那些对常见控件进行定制的模块。
- 导入Qt内置模块的版本号为对应的Qt版本的最高版本号。
- js文件导入到qml中必须要有别名。
- 在导入模块中,本身就有命名冲突时,需给其中至少一个模块都设置别名
- 不对 Qt 内置模块设置别名
- 对于自定义模块需设置别名
- 别名作为模块在所属 qml 文件中的代号,需保持文件内的唯一性
- 别名的命名规则采用“大驼峰”
2.4 根组件
qml文件描述的实际上一个由 “UI组件节点” 组成的“树”。而“根组件”也就是“根节点”,在qml文件有且只有一个。
根组件作为逻辑上的顶层组件,直接承担起了 qml 文件的所有定义,其属性、信号、方法即为该 qml 组件的属性、信号、方法。其他组件只能作为其子节点存在,对外是不可见的
2.4.1 根组件类型
- 组件模块
如果该qml文件声明的是对已有组件进行改造的可复用的组件,比如 “ImageButton”,那么该根组件应该为“Button”或者其他的什么“Button”,对应的别名应该设置为“button”或“root”。 - 功能界面模块
如果该qml文件声明的是一个复合的功能型界面,比如说“ReplaybackPanel”,“DataDelegateItem”,它是一系列组件的组合,一般将根组件设定为“Item”或者“Rectange”,其别名应设置为“root”。
2.4.2 根组件定义(具体介绍见语法部分)
- id
- 自定义属性property
- 信号signal
- JavaScript function
- 自带属性设置object properties
- 子控件child objects
- 状态states
- 动画animation、渐变transitions
Rectangle {
id: root
/*! 鼠标按下状态,当鼠标按下时为true */
property bool pressed: false
/*! 图片资源 */
property alias source: photoImage.source
/*! 鼠标点击事件 */
signal clicked
/*! 返回photoImage的width */
function doSomething()
{
return photoImage.width
}
width: {
if (photoImage.width > 200) {
photoImage.width;
} else {
200;
}
}
height: 480
color: "gray"
Rectangle {
id: photoRect
x: 20
y: 20
width: parent.width
height: 200
color: "white"
Image {
id: photoImage
anchors.centerIn: parent
}
}
MouseArea {
anchors.fill: parent
onPressed: {
root.pressed = true
}
onClicked: {
root.clicked()
}
}
states: State {
name: "selected"
when: root.pressed
PropertyChanges {
target: root.border
color: "red"
}
}
transitions: Transition {
from: ""
to: "selected"
ColorAnimation {
target: root.border
duration: 200
}
}
}
2.5 注释
2.5.1 文件功能注释
文件功能注释是对此qml大概功能的一个概述,若此qml文件还作为控件别的qml文件使用,则还有写出大概的使用方法。
/*!
将一个model的数据以下拉框列表的形式显示,通过选择下拉框列表数据,改变当前显示的数据
\qml
ComboBox {
width: 200
model: [ "Banana", "Apple", "Coconut" ]
}
\endqml
*/
注释以“/!”开始,以“ /” 结束,包含的对文件功能的说明,和控件的使用方法,使用用例以“\qml”开始,以“\endqml”结束。
2.5.2 自定义属性、信号、方法注释
自定义的属性、信号、方法必须添加注释。
自定义属性、信号、方法注释格式为:“/! /”,写在其定义的上一行。
/*! ComboBox下拉框列表当前选中的index值 */
property int currentIndex: 0
2.5.3 其他注释
这里的其它注释是指除文件功能注释和自定义属性、信号、方法注释外的其它需要注释的代码。
代码注释格式为:“ // xxxxxxxxx ”,写在被注释代码上方
// temporarily set fillIndex to new item
fillIndex = __items.length
2.6 规范补充
2.6.1 一行写一条语句
id: rootRect
x: 10
y: 10
width: 100
height: 100
...
2.6.2 组属性的设置
同一组属性,放到组中
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: 10
anchors.leftMargin: 10
如下代替上述代码
anchors {
top: parent.to
left: parent.left
topMargin: 10
leftMargin: 10
}
2.6.3 优先C++
Qml中和c++中都可以处理的逻辑,优先C++,提高效率
2.7 常用控件的缩写
Button -> btn
CheckBox -> chk
ComboBox -> cmb
RadioButton -> rdo
Text -> txt
Label -> lbl
Image -> img
DateTimePicker -> dtp
ListView -> lvw
ToolTip -> tip
GroupBox -> grp
Panel -> pnl
Calendar -> cal
TreeView ->trvw
ListView->lvw
GridView -> gvw
Repeater->rpt
Menu ->mnu
ProgressBar ->prg
3 基本语法
Rectangle {
id: root
/*! 鼠标按下状态,当鼠标按下时为true */
property bool pressed: false
/*! 图片资源 */
property alias source: photoImage.source
/*! 鼠标点击事件 */
signal clicked
/*! 返回photoImage的width */
function doSomething()
{
return photoImage.width
}
width: {
if (photoImage.width > 200) {
photoImage.width;
} else {
200;
}
}
height: 480
color: "gray"
Rectangle {
id: photoRect
x: 20
y: 20
width: parent.width
height: 200
color: "white"
Image {
id: photoImage
anchors.centerIn: parent
}
}
MouseArea {
anchors.fill: parent
onPressed: {
root.pressed = true
}
onClicked: {
root.clicked()
}
}
states: State {
name: "selected"
when: root.pressed
PropertyChanges {
target: root.border
color: "red"
}
}
transitions: Transition {
from: ""
to: "selected"
ColorAnimation {
target: root.border
duration: 200
}
}
}
3.1 导入语句
类似include,python也是这样用的
import QtQuick 2.9
import QtQuick.Window 2.2
/* QML文档可以看做是一个QML对象树,这里创建了Window根对象
和它的子对象Text */
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Text {
id: text1
text: qsTr("hello QML!")
}
}
代码中使用了 Window 类型,对应导入了 QtQuick.Window 模块。Window类型可以为 Qt Quick 场景创建一个顶级窗口,所以它一般作为根对象,在其中可以创建其他QML对象。
3.2 类型(QML Types)
基本类型、 QML 对象类型和 JavaScript 类型
- 基本类型
int 、string 等 - 对象类型(QML Object Types)
QML对象类型可以通过类型名称{对象特性} 的格式来定义一个对象。 - JavaScript 类型
QML支持JavaScript对象和数组,可以通过var 类型创建并存储任何标准的JavaScript类型。
property var theArray: []
property var theDate: new Date()
3.3 对象
QML对象由类型指定,一般与类型同名,名称以大写字母开头,后面跟一对大括号,在括号中包含了对象特性(QML Object Attributes)定义,包括 id、属性、信号、信号处理器、方法、附加属性和附加信号处理器等,也可包含子对象。
3.4 属性
可以分配一个静态的值或者绑定一个动态表达式,属性和值由一个冒号隔开,使用“属性 : 值”语法进行初始化,比如width: 640 。属性可以分行写,这样结尾可以不用分号,也可以写在一行,中间使用分号隔开。
3.5 注释
单行注释使用 “ // ” 开始,直到行末结束;多行注释使用 “ / ” 开始,以 “ / ” 结尾。
3.6 锚布局
Rectangle {
anchors.left: text1.right
anchors.leftMargin: 10
anchors.verticalCenter: text1.verticalCenter
}
anchors.left: parent.left
anchors.leftMargin: 10
anchors.top: parent.top
anchors.topMargin: 10
anchors 翻译过来就是锚,使用它可以进行简单的布局,当然这只是QML布局中的一种方法,不过很常用。anchors可以在一个部件的上、下、左、右、水平居中、垂直居中、中心等位置进行锚定。
anchors.centerIn: parent 就是锚定在了其父对象的中心;
anchors.left: text1.right 将绿色圆形的左侧与文本的右侧进行锚定,效果就是绿色圆形紧挨文本右侧放置;
anchors.leftMargin: 10 表明绿色圆形左侧的边距为10;
anchors.verticalCenter: text1.verticalCenter 表明绿色圆形的垂直居中位置锚定到文本的垂直居中位置,效果就是绿色圆形与文本在同一行上,且中心线对齐
3.7 JavaScript表达式和属性绑定
height: width ,这也被称作属性绑定,当 width 的值改变时,height 属性的值会跟随变化。
3.8 交互(如鼠标)
MouseArea是常用的交互方式。
MouseArea {
anchors.fill: parent
onClicked: {
// TODO
}
}
MouseArea对象中 anchors.fill: parent 表明让MouseArea填充整个父对象,这里就是绿色圆形,所以我们可以使用鼠标点击绿色圆形的任何部位来进行交互。当鼠标点击后,就可以在MouseArea中使用 onClicked:{} 来执行想要进行的操作。
3.9 调试输出
在QML中一般使用console将需要的信息输出到控制台,可用的有console.log, console.debug, console.info, console.warn 和 console.error,比如这里使用了console.debug("colorRect: ", parent.color) ,可以顺序输出参数中的内容,可以是字符串,也可以是对象属性引用。
4 中级语法
4.1 界面细节美化
4.1.1 美化字体和圆形
4.1.2 添加装饰图片
Image {
id: backImg
source: "images/show.png"
width: parent.width
anchors.bottom: parent.bottom
fillMode: Image.PreserveAspectFit
}
source指明路径,比如这里的 “images/show.png”
填充模式 Image.PreserveAspectFit 表明在缩放图片时会保持宽高比不变,这样图片不会被拉伸变形。
4.1.3 实现圆形的交互特效
4.1.4 复制圆形按钮
4.2 自定义组件
4.2.1 自定义对象类型和组件
4.2.2 自定义信号
4.2.3 自定义属性
4.2.4 自定义方法
5
参考
1、yafeilinux的Quick入门
2、Qt5 QML 学习资料整理
3、A Book about Qt5
4、Text QML Type
5、QML学习笔记(三)-引入Font-awesome
6、QML,QtQuick2.0以上常用控件
7、qml编码规范与指导
8、qml编程规范–名字(命名规范)