基本语法

  • QML 是一种用于描述对象如何相互关联的声明式语言
  • QtQuick是一种基于QML的框架

简单示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import QtQuick      /*导入模块,qt6可以不写版本号,自动加载最高版本的模块*/ 
Rectangle{
id:root
width: 220
height: 260
color:"#4A4A4A"

Image {
id: image
source: "../../ai2.jpg"
width: 80; height: 80
x: (root.width - image.width) / 2; y: (root.height- image.height) / 2
}

Text{
//un-named
text: "aaaaai"
width: root.width
horizontalAlignment: Text.AlignHCenter
y: image.y + 50
}
}
  • 每个QML文件都需要一个唯一的根元素
  • QML文档中的任意元素可以通过使用其id进行访问
  • 元素可以嵌套,子元素可以使用parent关键字访问父元素
  • 可以使用 property限定符向元素添加新属性, 例如property int times:24
  • 使用别名关键字 `property alias + 名称 : 引用
  • grouped property `font{family:”Ubuntu”;pixelSize:24}

核心元素类型

  • Rectangle

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
        //自定义渐变色
    Rectangle{
    id:rect3
    x:250; y:10
    width:76; height:96
    gradient: Gradient{
    GradientStop{position:0; color:'red'}
    GradientStop{position:1; color:'blue'}
    }
    // 0代表顶部 1代表底部

    border.color: "lightsteelblue"
    border.width:4
    radius:10
    }
  • Text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        Rectangle{
    id:rect3
    x:250; y:10
    width:76; height:96
    gradient: Gradient{
    GradientStop{position:0; color:'red'} // 0代表顶部 1代表底部
    GradientStop{position:1; color:'blue'}
    }
    border.color: "lightsteelblue"
    border.width:4
    radius:10
    }
  • Image

    1
    2
    3
    4
    5
    6
    7
        Image{
    id: img1
    source: "../../ai2.jpg"
    //fillMode: Image.stretch
    //fillMode: Image.PreserveAspectCrop
    fillMode: Image.PreserveAspectFit
    }
  • MouseArea

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
        Rectangle{
    id:rect1
    x:12; y:12
    width: 76; height:96
    color: "lightsteelblue"
    MouseArea{
    id:area
    width: parent.width
    height: parent.height
    onClicked: rect2.visible = !rect2.visible
    }
    }
    Rectangle{
    id:rect2
    x:112; y:12
    width: 76; height:96
    border.color: "lightsteelblue"
    border.width:4
    radius:8
    }
  • TextInput 文本输入

  • TextEdit

组件

  • 组件是可重复使用的元素,最简单的形式是基于文件的组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

// Button.qml

import QtQuick
Item {
id: root
property alias text: label.text
signal clicked
Rectangle{
id: button
x: 12; y: 12
width: 116
height: 25
color: "lightsteelblue"
border.color: "slategrey"

Text{
id: label
anchors.centerIn: parent
text: "Start"
}

MouseArea{
anchors.fill: parent
onClicked:{
root.clicked()
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import QtQuick

Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Button{
text: "test"
onClicked:{
status.text = "Button has been clicked";
}
}

Text{
id: status
x: 12
y: 76
width: 116
height: 26
text: "waiting..."
horizontalAlignment: Text.ALignHCenter
}
}

简单变换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import QtQuick
Image{
id: root
signal clicked
MouseArea{
anchors.fill: parent
onClicked: root.clicked()
}

Behavior on rotation{
NumberAnimation{
duration: 500
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import QtQuick
Window {
width: 640
height: 480
visible: true
title: qsTr("Test")

MouseArea{
anchors.fill: parent
onClicked:{
a1.y = 180
a2.rotation = 0
a3.rotation = 0
a3.scale = 1;
}
}

ClickableImage{
id: a1
source: "../../ai2.jpg"
width:100
height:100
x:10
y:180
onClicked: {
y += 10 //平移
}
}

ClickableImage{
id: a2
source: "../../ai2.jpg"
width:100
height:100
x:210
y:180
onClicked: {
rotation += 180; //旋转
}
}

ClickableImage{
id: a3
source: "../../ai2.jpg"
width:100
height:100
x:410
y:180
onClicked:{
rotation += 180;
scale += 0.1 //缩放
}
}
}

定位器

  • Row

    1
    2
    3
    4
    5
    6
    7
    8
    Row{
    id:row
    anchors.centerIn: parent
    spacing: 10
    RedSquare{}
    GreenSquare{}
    BlueSquare{}
    }
  • Column

    1
    2
    3
    4
    5
    6
    7
    8
    Column{
    id:column
    anchors.centerIn: parent
    spacing: 10
    RedSquare{}
    GreenSquare{}
    BlueSquare{}
    }
  • Grid

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Grid{
    id:grid
    anchors.centerIn: parent
    spacing:10
    rows:2
    columns:3
    RedSquare{}
    GreenSquare{}
    BlueSquare{}
    RedSquare{}
    GreenSquare{}
    BlueSquare{}
    }
  • Flow

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Flow{
    id:flow
    anchors.fill: parent
    anchors.margins: 20
    spacing: 20
    RedSquare{}
    GreenSquare{}
    BlueSquare{}
    RedSquare{}
    GreenSquare{}
    BlueSquare{}
    }

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
GraySquare{
id: root
width: 252
height: 252
property var colorArray: ["#00bde3", "#67c111", "#ea7025"]
Grid{
anchors.centerIn: parent
anchors.margins: 8
spacing: 4
//columns默认值为4
Repeater{
model:16
Rectangle{
id:rect
property int colorIndex: Math.floor(Math.random() * 3)
color: root.colorArray[colorIndex]
width: 56; height: 56
Text{
anchors.centerIn: parent
text: "Cell" + rect.positionerindex()
}
}
}
}
}

布局

  • qml 使用锚来布局项目
    • 文本元素除了上图的锚外还有baseline,是指文本所在的线,如果item没有文字则baselinetop的位置是相同的

键盘输入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import QtQuick

Window {
width: 640
height: 480
visible: true
title: qsTr("Test")

Rectangle{
color:'gray'
anchors.fill: parent
width:650
height:480

Rectangle{
id:rect
width:50;height:50
color:'blue'
x:100;y:100

Image{
anchors.fill: parent
source: "../../ai2.jpg"
}
}

focus:true
Keys.onLeftPressed: rect.x -= 8
Keys.onRightPressed: rect.x += 8
Keys.onUpPressed: rect.y -= 8
Keys.onDownPressed: rect.y += 8

Keys.onPressed: function(event){
switch(event.Key){
case Qt.key_Plus:
rect.scale += 0.2
break;
case Qt.Key_Minus:
rect.scale -= 0.2
break;
}
}
}
}

动画

QML 动画使用插值的方式控制属性的更改

常用的动画类型元素动画:

  • PropertyAnimation: 属性值改变播放动画
  • NumberAnimation: qreal-type值改变播放动画
  • ColorAnimation: 颜色值改变播放动画
  • RotationAnimation: 旋转值改变播放的动画

eg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import QtQuick

Window {
id: root
width: 720
height: 480
visible: true
title: qsTr("Test")
Image{
anchors.fill: parent
source:"../../test.png"
}

property int padding :40
property bool running:false

Image{
id:ig
source: "../../ai2.jpg"
width:100
height:100
x:root.padding; y:(root.height - width) / 2

NumberAnimation on x{
to: root.width - ig.width - root.padding // ig.width
duration:2000
running:root.running
}

RotationAnimation on rotation{
to: 720
duration:2000
running:root.running
}

OpacityAnimator on opacity{
to: 0
duration:2000
running:root.running
}
}
MouseArea{
anchors.fill: parent
onClicked: root.running = true
}
}

可以通过多种方式执行动画

  • 属性上的动画: 在元素完全加载后自动运行
  • 属性上的行为: 属性值更改时自动运行
  • 独立动画: 使用start()显示启动动画或将running设置为true时运行

eg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import QtQuick

Window {
id: root
width: 640
height: 480
visible: true
color: 'gray'
title: qsTr("Test")

ClickableImage{
id:a1
source: "../../ai2.jpg"


x: 30; y:root.height - a2.height
text:"annimation on property"

NumberAnimation on y{
to: 40
duration: 2000
}
}

ClickableImage{
id:a2
source: "../../ai2.jpg"


x: 30 + 150; y:root.height- a2.height
text:"animation on behavior"

Behavior on y{
NumberAnimation{duration:2000}
}

onClicked: y=20

}

ClickableImage{
id:a3
source: "../../ai2.jpg"

x: 30 + 350; y:root.height- a2.height
text:"Independent animation"

onClicked: anim.restart()
NumberAnimation{
id:anim
target: a3
property:"y"
to: 40
from: root.height-a2.height
duration: 2000
running: area.pressed
}
}
MouseArea{
id:area
anchors.fill: parent
}
}