初识QML
QML是对JavaScript的一种扩展,可以让开发者和设计者利用一个声明性语法来使用QML元素指定每一个用户界面。
QML完善了JavaScript和Qt现有的基于QObject的类型系统间的整合,在语言级别上添加了对自动属性绑定和透明网络传输的支持。
QML通过QtDeclarative模块便可以完全支持从C十进行扩展。
QML文件是可以直接运行而不需要进行编译的。运行 QML文件的是一个被称为qmlviewer.exe的程序,它在Qt安装目录下的bin目录中。
QML程序中默认使用的是UTF-8编码。可以选择“编辑一选择编码”菜单项,在打开的对话框中选择UTF-8,然后按下“根据编码重新载入”按钮。
1.02 QML 基本类型, 是“类型安全”的。它们只允许分配一个匹配该属性类型的值。
类型 |
描述 |
action |
action类型拥有QAction的所有属性 |
bool |
布尔类型是一个二进制值,有true和false两个值 |
color |
一个color就是一个标准的颜色名称加上引号,例如“red” |
date |
一个 date 被指定为“YYYY-MM-DD” |
double |
-个double数字包含一个小数点,并使用双精度进行存储 |
enumeration |
一个枚举类型包含一组已命名的值 |
font |
font类型包含了QFont的属性 |
int |
整型包含所有的数字,例如0,10,或者一20 |
list |
一个对象列表 |
point |
一个point类型,包含了一个x和一个y属性 |
real |
一个real数字包含了一个小数点,例如1.2或者-29.8 |
rect |
一个rect类型包含了x、y,width和height属性 |
size |
一个size类型包含了width和height属性 |
string |
一个string是一个在引号中的任意格式的文本,例如“Helloworld!” |
time |
一个time被指定为“hh:mm:ss” |
url |
一个URL是一个资源定位器,像一个文件名 |
variant |
一个variant类型是一个通用的属性类型 |
vector3d |
一个vector3d类型包含x、y和z属性 |
1.03 QML的属性类型
QML类型 |
默认值 |
c++类型 |
int |
0 |
int |
bool |
false |
bool |
double |
0.0 |
double |
real |
0.0 |
double |
string |
'' |
QString |
url |
'' |
QUrl |
color |
#000000 |
QColor |
date |
未定义 |
QDateTime |
variant |
未定义 |
QVariant |
1.04 属性绑定
1. 使用:对属性进行绑定
Rectangle{
width: otherItem.width
height: otherItem.height
}
2. QML扩展了标准的JavaScript引擎,所以任何可用的JavaScript表达式都可以用作属性绑定,
在绑定中可以访问对象属性,调用函数,甚至可以使用Date和Math等内建的JavaScript对象。
anchors.centerIn: parent //绑定对象属性
width:Math.min(otherItem.width, 10) //绑定函数
height: calculateMyHeight()
color:{if(width>10)"blue";else "red"}
3. 使用=对已经绑定的对象赋值,如果给已经进行了绑定的属性进行赋值,那么将会移除绑定。
一个属性在一个时间只能拥有一个值,如果任何代码明确的为其设置了值,那么绑定将会被移除。
4. 定义一个新的属性:[default] property <type> <name> [:defaultValue]
property string myName: 'xiaoming'
1.05 属性更改通知
当一个属性更改值时,它会发送一个信号来告知这个更改。
要获取这个信号,只需要创建一个信号处理器(signal handler),使用“on<Property>Changed”语法来命名。
例如,Rectangle元素拥有width和color属性,Rectangle对象中定义了两个信号处理器
无论何时属性被修改了,都会自动调用它们。
Rectangle{
width: 100;height: 100
onWidthChanged: console.log("width changed")
onHeightChanged: console.log("height changed")
}
1.06 更改属性绑定(states)与过度(Transitions)
PropertyChanges元素可以用在一个状态改变中来修改属性的绑定。
ColorAnimation过渡由状态的改变触发执行。你可以使用属性的from:和t0:来定义状态改变的指定过渡。
这两个属性就像一个过滤器,当过滤器为tue时,过渡生效。你也可以使用“"来表示任何状态。
from:'';to:'*'表示从任一状态到另一个任一状态的默认值,这意味着过渡用于每个状态的切换。
import QtQuick 2.0
Rectangle {
id: root
width: 800
height: 600
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: {
light1.state = ( light1.state == 'stop' ? "go" : 'stop' )
light2.state = ( light2.state == 'go' ? 'stop' : 'go' )
console.log('light1.state : ',light1.state);
console.log('light2.state : ',light2.state);
}
}
Rectangle {
id: light1
x:24; y:15
width: 100; height: 100
radius: width/2
color: 'black'
states: [
State {
name: "stop"
PropertyChanges { target: light1; color: 'red' }
},
State {
name: "go"
PropertyChanges { target: light2; color: 'green' }
}
]
/*状态过度,延时2s*/
transitions: [
Transition {
from: "stop"; to: "go"
ColorAnimation{ target: light1; properties: 'color'; duration: 2000 }
ColorAnimation{ target: light2; properties: 'color'; duration: 2000 }
}
]
}
Rectangle {
id: light2
x:24; y:135
width: 100; height: 100
radius: width/2
color: 'black'
}
}
1.07 绑定元素
从c++中暴露的属性(system.brightness)绑定到一个来自 QML的值(slider.value)就需要使用到绑定元素。
Binding{
target: system
property: 'brightness'
value: slider.value
}
1.08 属性别名
1. 属性别名是更高级的属性声明形式。
2. 与定义一个属性不同,定义一个属性会为该属性分配新的、独立的存储空间,
而 属性别名 会将新声明的属性(称为别名属性) 作为一个已经存在的属性 (被别名的属性)的直接引用。
对别名属性的读/写操作 等价于 对被别名的属性进行读/写操作。
3. 属性别名对于允许外部对象直接修改和访问一个组件中的子对象是很有用的
4. 属性别名的声明语法如下:
[defaul] tproperty alias <name>:<alias reference>
1.09 组件中添加函数
QML组件中可以定义JavaScript代码的函数,这些函数可以在内部调用,也可以被其他对象调用。
Rectangle {
id: rootRect
width: 800
height: 600
visible: true
function say(test){
console.log('said: ', test);
}
MouseArea {
anchors.fill: parent
onClicked: rootRect.say("hello world")
}
}
1.09 组件中添加信号
1. 当一个事件发生时,可以使用信号通知其他对象。
定义一个新的信号的语法如下:
signal <name>[([<type><parameter name>[,...]])] 如:
Item{
signal clicked
signal hovered()
signal performAction(string action, variant actionArgument)
}
2. 发射信号就是简单调用它,就像操作函数一样。
Rectangle {
id: rect1
signal buttonClicked
width: 100; height:100
MouseArea {
anchors.fill: parent
onClicked: rect1.buttonClicked()
}
}
1.10 将信号关联到其他函数和信号上
1. 信号对象有一个connect()函数,可以用来将一个信号关联到一个函数或者其他的信号上。
当一个信号关联到一个函数上,这个函数会在信号发射时自动调用。
/*Button.qml*/
import QtQuick 2.0
Rectangle{
id: rect
signal buttonClicked (int xPos, int yPos)
width: 100; height: 100
color: 'red'
MouseArea {
anchors.fill: parent
onClicked: rect.buttonClicked(mouse.x, mouse.y)
}
}
import QtQuick 2.12
import QtQuick.Window 2.12
Rectangle {
id: rootRect
width: 800
height: 600
visible: true
Item {
id: item
width: 200; height: 200
function myMethod(){
console.log('Button was clicked')
}
Button {
id:button
anchors.fill: parent
Component.onCompleted: buttonClicked.connect(item.myMethod)
}
}
}
2. 在大多数情况下,使用信号处理器来接收信号就足够了,因为这里的代码使用connect()函数比以前使用onButtonClicked处理器没有任何的优势。
然而,如果要动态创建对象或者集成JavaScript代码,就会发现connect()函数很有用。