QML 语法基础学习笔记
- [QML 语法基础:从对象、属性到属性绑定](#QML 语法基础:从对象、属性到属性绑定)
-
- [一、QML 是什么](#一、QML 是什么)
- 二、import:导入模块
- [三、QML 对象](#三、QML 对象)
- [四、属性与 id](#四、属性与 id)
-
- [4.1 什么是属性](#4.1 什么是属性)
- [4.2 id 的作用](#4.2 id 的作用)
- 五、父对象与子对象
- [六、QML 中的布局方式](#六、QML 中的布局方式)
- [七、QML 注释](#七、QML 注释)
-
- [7.1 单行注释](#7.1 单行注释)
- [7.2 多行注释](#7.2 多行注释)
- 八、表达式
- 九、属性绑定
- 十、固定值与属性绑定的区别
- 十一、自定义属性
- 十二、信号与事件处理
- [十三、QML 调试输出](#十三、QML 调试输出)
- 十四、完整示例:矩形、按钮与属性绑定
- 十五、容易混淆的知识点
-
- [15.1 id 不是普通属性](#15.1 id 不是普通属性)
- [15.2 属性绑定会自动更新](#15.2 属性绑定会自动更新)
- [15.3 赋值可能破坏原来的绑定](#15.3 赋值可能破坏原来的绑定)
- [15.4 anchors 与 x、y 不要随意混用](#15.4 anchors 与 x、y 不要随意混用)
- [15.5 Rectangle 与 Button 所属模块不同](#15.5 Rectangle 与 Button 所属模块不同)
- 十六、本节知识总结
- 十七、快速复习清单
- 十八、一句话记忆
- [QML 语法基础:从对象、属性到属性绑定](#QML 语法基础:从对象、属性到属性绑定)
-
- [一、QML 是什么](#一、QML 是什么)
- 二、import:导入模块
- [三、QML 对象](#三、QML 对象)
- [四、属性与 id](#四、属性与 id)
-
- [4.1 什么是属性](#4.1 什么是属性)
- [4.2 id 的作用](#4.2 id 的作用)
- 五、父对象与子对象
- [六、QML 中的布局方式](#六、QML 中的布局方式)
- [七、QML 注释](#七、QML 注释)
-
- [7.1 单行注释](#7.1 单行注释)
- [7.2 多行注释](#7.2 多行注释)
- 八、表达式
- 九、属性绑定
- 十、固定值与属性绑定的区别
- 十一、自定义属性
- 十二、信号与事件处理
- [十三、QML 调试输出](#十三、QML 调试输出)
- 十四、完整示例:矩形、按钮与属性绑定
- 十五、容易混淆的知识点
-
- [15.1 id 不是普通属性](#15.1 id 不是普通属性)
- [15.2 属性绑定会自动更新](#15.2 属性绑定会自动更新)
- [15.3 赋值可能破坏原来的绑定](#15.3 赋值可能破坏原来的绑定)
- [15.4 anchors 与 x、y 不要随意混用](#15.4 anchors 与 x、y 不要随意混用)
- [15.5 Rectangle 与 Button 所属模块不同](#15.5 Rectangle 与 Button 所属模块不同)
- 十六、本节知识总结
- 十七、快速复习清单
- 十八、一句话记忆
- [QML 语法基础:从对象、属性到属性绑定](#QML 语法基础:从对象、属性到属性绑定)
-
- [一、QML 是什么](#一、QML 是什么)
- 二、import:导入模块
- [三、QML 对象](#三、QML 对象)
- [四、属性与 id](#四、属性与 id)
-
- [4.1 什么是属性](#4.1 什么是属性)
- [4.2 id 的作用](#4.2 id 的作用)
- 五、父对象与子对象
- [六、QML 中的布局方式](#六、QML 中的布局方式)
- [七、QML 注释](#七、QML 注释)
-
- [7.1 单行注释](#7.1 单行注释)
- [7.2 多行注释](#7.2 多行注释)
- 八、表达式
- 九、属性绑定
- 十、固定值与属性绑定的区别
- 十一、自定义属性
- 十二、信号与事件处理
- [十三、QML 调试输出](#十三、QML 调试输出)
- 十四、完整示例:矩形、按钮与属性绑定
- 十五、容易混淆的知识点
-
- [15.1 id 不是普通属性](#15.1 id 不是普通属性)
- [15.2 属性绑定会自动更新](#15.2 属性绑定会自动更新)
- [15.3 赋值可能破坏原来的绑定](#15.3 赋值可能破坏原来的绑定)
- [15.4 anchors 与 x、y 不要随意混用](#15.4 anchors 与 x、y 不要随意混用)
- [15.5 Rectangle 与 Button 所属模块不同](#15.5 Rectangle 与 Button 所属模块不同)
- 十六、本节知识总结
- 十七、快速复习清单
- 十八、一句话记忆
- [QML 语法基础:从对象、属性到属性绑定](#QML 语法基础:从对象、属性到属性绑定)
-
- [一、QML 是什么](#一、QML 是什么)
- 二、import:导入模块
- [三、QML 对象](#三、QML 对象)
- [四、属性与 id](#四、属性与 id)
-
- [4.1 什么是属性](#4.1 什么是属性)
- [4.2 id 的作用](#4.2 id 的作用)
- 五、父对象与子对象
- [六、QML 中的布局方式](#六、QML 中的布局方式)
- [七、QML 注释](#七、QML 注释)
-
- [7.1 单行注释](#7.1 单行注释)
- [7.2 多行注释](#7.2 多行注释)
- 八、表达式
- 九、属性绑定
- 十、固定值与属性绑定的区别
- 十一、自定义属性
- 十二、信号与事件处理
- [十三、QML 调试输出](#十三、QML 调试输出)
- 十四、完整示例:矩形、按钮与属性绑定
- 十五、容易混淆的知识点
-
- [15.1 id 不是普通属性](#15.1 id 不是普通属性)
- [15.2 属性绑定会自动更新](#15.2 属性绑定会自动更新)
- [15.3 赋值可能破坏原来的绑定](#15.3 赋值可能破坏原来的绑定)
- [15.4 anchors 与 x、y 不要随意混用](#15.4 anchors 与 x、y 不要随意混用)
- [15.5 Rectangle 与 Button 所属模块不同](#15.5 Rectangle 与 Button 所属模块不同)
- 十六、本节知识总结
- 十七、快速复习清单
- 十八、一句话记忆
QML 语法基础:从对象、属性到属性绑定
QML 是 Qt Quick 使用的一种声明式语言,主要用于快速构建图形界面。
相比传统的 C++ 界面开发,QML 的语法更加简洁直观。开发者只需要描述界面中有哪些对象、对象具有什么属性,以及对象之间有什么关系,就可以完成大部分界面开发工作。
本文整理 QML 中最基础、最常用的语法,包括:
import模块导入- QML 对象
- 属性与
id - 相对布局与绝对布局
- 注释
- 表达式
- 属性绑定
- 信号处理
- 调试输出
一、QML 是什么
QML,全称 Qt Modeling Language,是 Qt Quick 使用的声明式语言。
所谓声明式,可以简单理解为:
开发者主要描述"界面应该是什么样子",而不是一步一步告诉程序"应该怎样绘制界面"。
例如,下面的代码描述了一个红色矩形:
qml
Rectangle {
width: 200
height: 100
color: "red"
}
这段代码没有手动调用绘图函数,而是直接声明:
- 对象类型是
Rectangle - 宽度是
200 - 高度是
100 - 颜色是红色
QML 的主要特点包括:
- 语法简单,学习成本较低;
- 适合快速开发图形界面;
- 支持属性绑定;
- 支持动画和触摸交互;
- 可以与 JavaScript、C++ 配合使用;
- 适合桌面端、嵌入式设备和触摸屏应用。
二、import:导入模块
在使用 QML 组件之前,通常需要先导入组件所属的模块。
基本格式如下:
qml
import 模块名称 版本号
例如:
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Window
常见模块的作用如下:
| 模块 | 主要作用 |
|---|---|
QtQuick |
提供 Rectangle、Text、MouseArea 等基础类型 |
QtQuick.Controls |
提供 Button、Label、TextField 等控件 |
QtQuick.Window |
提供 Window 等窗口类型 |
QtQuick.Layouts |
提供 RowLayout、ColumnLayout 等布局类型 |
在部分 Qt 版本中,也可以写明版本号:
qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
如果没有导入组件所属的模块,程序可能会出现类似下面的错误:
text
Unknown component
或者:
text
Type Button unavailable
因此,可以把 import 理解为 C++ 中的 #include,但两者的具体机制并不完全相同。
三、QML 对象
QML 界面由一个个对象组成。
例如:
qml
Rectangle {
}
这里定义了一个 Rectangle 对象。
再例如:
qml
Button {
}
这里定义了一个 Button 对象。
可以将 QML 对象简单理解为 C++ 类创建出来的实例:
cpp
Rectangle rectangle;
Button button;
在 QML 中,对象通常采用下面的结构:
qml
对象类型 {
属性名: 属性值
子对象类型 {
属性名: 属性值
}
}
例如:
qml
Rectangle {
width: 300
height: 200
color: "lightgray"
Button {
text: "确定"
}
}
在这个例子中:
Rectangle是父对象;Button是Rectangle的子对象;- 按钮会显示在矩形内部。
四、属性与 id
4.1 什么是属性
属性用于描述对象的状态和外观。
例如:
qml
Rectangle {
width: 200
height: 100
color: "red"
opacity: 0.8
}
这里的属性包括:
width:宽度height:高度color:颜色opacity:透明度
按钮也有自己的属性:
qml
Button {
width: 120
height: 40
text: "确定"
font.pixelSize: 18
}
常见属性如下:
| 属性 | 作用 |
|---|---|
width |
设置宽度 |
height |
设置高度 |
x |
设置水平方向坐标 |
y |
设置垂直方向坐标 |
color |
设置颜色 |
text |
设置文本 |
visible |
控制是否可见 |
opacity |
设置透明度 |
font.pixelSize |
设置字体大小 |
4.2 id 的作用
id 是 QML 对象的唯一标识。
例如:
qml
Rectangle {
id: redRectangle
width: 200
height: 100
color: "red"
}
其他对象可以通过 redRectangle 访问这个矩形:
qml
Rectangle {
width: redRectangle.width / 2
height: 50
color: "blue"
}
需要注意:
- 同一个 QML 作用域中的
id不能重复; id不需要加引号;id通常使用小写字母开头;id是 QML 的特殊标识,不是普通属性;id创建后不能在运行期间修改。
正确写法:
qml
id: blueRectangle
错误写法:
qml
id: "blueRectangle"
五、父对象与子对象
QML 对象可以嵌套。
例如:
qml
Rectangle {
width: 400
height: 300
color: "lightgray"
Rectangle {
width: 100
height: 100
color: "red"
}
}
外层矩形是父对象,内层矩形是子对象。
子对象可以通过 parent 访问父对象:
qml
Rectangle {
width: parent.width / 2
height: parent.height / 2
color: "red"
}
这里表示:
- 子矩形宽度是父对象宽度的一半;
- 子矩形高度是父对象高度的一半。
六、QML 中的布局方式
QML 中常见的定位方式可以分为:
- 绝对定位;
- 相对定位;
- 布局管理器。
本节重点介绍前两种。
6.1 绝对定位
绝对定位通过 x 和 y 设置对象的位置。
qml
Rectangle {
width: 100
height: 100
x: 50
y: 80
color: "blue"
}
其中:
x表示对象左边距离父对象左边的距离;y表示对象顶部距离父对象顶部的距离。
QML 坐标系的原点通常位于父对象左上角:
text
(0, 0) ----------------> x
|
|
|
|
v
y
绝对定位的优点是简单直接,但当窗口大小发生变化时,对象的位置不会自动适配。
因此,绝对定位更适合:
- 固定尺寸的界面;
- 临时测试;
- 对位置要求非常明确的场景。
6.2 相对定位:anchors
anchors 可以让对象相对于父对象或其他对象进行定位。
居中显示
qml
Rectangle {
width: 100
height: 100
color: "red"
anchors.centerIn: parent
}
无论父窗口怎样变化,矩形都会保持居中。
水平居中
qml
anchors.horizontalCenter: parent.horizontalCenter
垂直居中
qml
anchors.verticalCenter: parent.verticalCenter
底部对齐
qml
anchors.bottom: parent.bottom
设置底部边距
qml
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
同时设置水平居中和底部对齐
qml
Button {
text: "确定"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
}
这样按钮会始终位于父对象底部,并保持水平居中。
6.3 常用 anchors 属性
| 属性 | 作用 |
|---|---|
anchors.left |
左边对齐 |
anchors.right |
右边对齐 |
anchors.top |
顶部对齐 |
anchors.bottom |
底部对齐 |
anchors.centerIn |
水平和垂直居中 |
anchors.horizontalCenter |
水平居中 |
anchors.verticalCenter |
垂直居中 |
anchors.fill |
填充目标对象 |
anchors.margins |
设置统一边距 |
anchors.leftMargin |
设置左边距 |
anchors.rightMargin |
设置右边距 |
anchors.topMargin |
设置顶部边距 |
anchors.bottomMargin |
设置底部边距 |
例如,让子对象填满父对象:
qml
Rectangle {
anchors.fill: parent
color: "lightblue"
}
设置统一边距:
qml
Rectangle {
anchors.fill: parent
anchors.margins: 20
color: "lightblue"
}
七、QML 注释
QML 的注释方式和 C、C++、JavaScript 类似。
7.1 单行注释
qml
// 这是一行注释
Rectangle {
width: 100 // 设置矩形宽度
}
7.2 多行注释
qml
/*
这是多行注释
可以连续注释多行内容
*/
例如:
qml
/*
Rectangle {
width: 100
height: 100
color: "gray"
}
*/
在 Qt Creator 中,通常可以使用快捷键:
text
Ctrl + /
对选中的代码进行注释或取消注释。
八、表达式
QML 属性值不仅可以是固定值,也可以是表达式。
例如:
qml
Rectangle {
width: parent.width / 2
height: parent.height / 2
}
这里使用了除法表达式。
常见运算符包括:
| 类型 | 运算符 |
|---|---|
| 加法 | + |
| 减法 | - |
| 乘法 | * |
| 除法 | / |
| 取余 | % |
| 大于 | > |
| 小于 | < |
| 等于 | === |
| 不等于 | !== |
| 逻辑与 | && |
| 逻辑或 | ` |
| 逻辑非 | ! |
例如:
qml
Rectangle {
width: parent.width - 40
height: width / 2
visible: parent.width > 300
}
也可以使用条件表达式:
qml
color: width > 200 ? "red" : "blue"
这表示:
- 当宽度大于
200时,颜色为红色; - 否则颜色为蓝色。
九、属性绑定
属性绑定是 QML 最重要的特性之一。
当一个属性使用了另一个属性的值时,QML 会自动建立绑定关系。
例如:
qml
Rectangle {
id: redRectangle
width: 200
height: 100
color: "red"
}
Rectangle {
id: blueRectangle
width: redRectangle.width / 2
height: 100
color: "blue"
}
这里蓝色矩形的宽度绑定到了红色矩形的宽度:
qml
width: redRectangle.width / 2
当红色矩形的宽度发生变化时,蓝色矩形的宽度也会自动变化。
例如:
qml
Button {
text: "增加宽度"
onClicked: {
redRectangle.width += 10
}
}
每次点击按钮:
- 红色矩形宽度增加
10; - 蓝色矩形的宽度自动重新计算;
- 不需要手动修改蓝色矩形。
这就是属性绑定的优势:
一个属性发生变化后,依赖它的属性会自动更新。
十、固定值与属性绑定的区别
固定值:
qml
width: 100
表示宽度始终是 100。
属性绑定:
qml
width: parent.width / 2
表示宽度会根据父对象宽度动态变化。
例如:
qml
Window {
width: 800
height: 600
Rectangle {
width: parent.width / 2
height: parent.height / 2
color: "red"
}
}
当窗口大小变化时,矩形会始终保持为窗口宽度和高度的一半。
十一、自定义属性
除了 QML 对象自带的属性,还可以通过 property 定义自定义属性。
基本格式如下:
qml
property 属性类型 属性名称: 默认值
例如:
qml
Rectangle {
property int count: 0
property string title: "QML 学习"
property bool enabledState: true
property real scaleValue: 1.5
}
常见属性类型如下:
| 类型 | 说明 |
|---|---|
int |
整数 |
real |
小数 |
double |
双精度小数 |
bool |
布尔值 |
string |
字符串 |
color |
颜色 |
url |
地址 |
var |
任意类型 |
按钮点击时可以修改自定义属性:
qml
Button {
text: "增加"
onClicked: {
count += 1
}
}
十二、信号与事件处理
QML 控件可以通过信号处理器响应用户操作。
例如,按钮具有 clicked 信号,对应的处理器是:
qml
onClicked
完整示例:
qml
Button {
text: "点击按钮"
onClicked: {
console.log("按钮被点击")
}
}
常见事件处理器包括:
| 处理器 | 作用 |
|---|---|
onClicked |
鼠标点击 |
onPressed |
鼠标按下 |
onReleased |
鼠标释放 |
onDoubleClicked |
鼠标双击 |
onWidthChanged |
宽度发生变化 |
onHeightChanged |
高度发生变化 |
onTextChanged |
文本发生变化 |
例如:
qml
Rectangle {
width: 100
onWidthChanged: {
console.log("当前宽度:", width)
}
}
十三、QML 调试输出
QML 可以使用 console 输出调试信息。
普通输出
qml
console.log("程序运行")
调试信息
qml
console.debug("调试信息")
警告信息
qml
console.warn("警告信息")
错误信息
qml
console.error("错误信息")
也可以一次输出多个值:
qml
console.log("矩形坐标:", blueRectangle.x, blueRectangle.y)
在 Qt Creator 中,可以在下面的位置查看输出:
text
Application Output
也就是"应用程序输出"窗口。
十四、完整示例:矩形、按钮与属性绑定
下面通过一个完整案例练习本节涉及的主要语法。
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Window
Window {
id: rootWindow
width: 800
height: 600
visible: true
title: "QML 语法基础示例"
Rectangle {
id: redRectangle
width: 200
height: 120
color: "red"
radius: 8
anchors.centerIn: parent
}
Rectangle {
id: blueRectangle
// 蓝色矩形的宽度绑定到红色矩形宽度的一半
width: redRectangle.width / 2
height: 80
color: "blue"
radius: 8
x: 30
y: 30
}
Button {
id: addButton
text: "增加宽度"
font.pixelSize: 16
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.leftMargin: 20
anchors.bottomMargin: 20
onClicked: {
redRectangle.width += 10
console.log("增加按钮被点击")
console.log("红色矩形宽度:", redRectangle.width)
console.log("蓝色矩形宽度:", blueRectangle.width)
}
}
Button {
id: subtractButton
text: "减小宽度"
font.pixelSize: 16
anchors.left: addButton.right
anchors.bottom: parent.bottom
anchors.leftMargin: 10
anchors.bottomMargin: 20
onClicked: {
if (redRectangle.width > 50) {
redRectangle.width -= 10
}
console.log("减小按钮被点击")
console.log("红色矩形宽度:", redRectangle.width)
console.log("蓝色矩形宽度:", blueRectangle.width)
}
}
Button {
id: moveButton
text: "移动蓝色矩形"
font.pixelSize: 16
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 20
anchors.bottomMargin: 20
onClicked: {
blueRectangle.x += 16
console.log("蓝色矩形当前 x 坐标:", blueRectangle.x)
}
}
}
这个示例包含:
- 使用
import导入模块; - 创建
Window、Rectangle和Button对象; - 使用
id标识对象; - 使用
width、height、color等属性; - 使用
anchors进行相对定位; - 使用
x和y进行绝对定位; - 使用表达式计算属性;
- 使用属性绑定联动两个矩形;
- 使用
onClicked处理按钮点击; - 使用
console.log()输出调试信息。
十五、容易混淆的知识点
15.1 id 不是普通属性
qml
id: redRectangle
id 是对象的特殊标识,不能像普通属性一样动态修改。
15.2 属性绑定会自动更新
qml
width: redRectangle.width / 2
只要 redRectangle.width 变化,这里的宽度就会自动重新计算。
15.3 赋值可能破坏原来的绑定
假设最开始存在属性绑定:
qml
width: redRectangle.width / 2
如果之后在 JavaScript 代码中直接赋值:
qml
blueRectangle.width = 300
原来的绑定关系通常会被新的固定值替代。
此后红色矩形宽度变化时,蓝色矩形宽度可能不再自动更新。
因此,开发时需要区分:
- 声明属性绑定;
- 在事件处理器中直接赋值。
15.4 anchors 与 x、y 不要随意混用
例如,一个对象已经设置:
qml
anchors.horizontalCenter: parent.horizontalCenter
这时再设置:
qml
x: 100
可能无法得到预期结果,因为 anchors 正在负责对象的水平位置。
一般建议:
- 使用
anchors时,让anchors管理对应方向的位置; - 使用
x、y时,不要再对同一方向设置锚点。
15.5 Rectangle 与 Button 所属模块不同
Rectangle 通常来自:
qml
import QtQuick
Button 通常来自:
qml
import QtQuick.Controls
因此,只导入 QtQuick 时,不一定能直接使用 Button。
十六、本节知识总结
QML 的基础语法可以归纳为下面几个关键词:
| 关键词 | 作用 |
|---|---|
import |
导入 QML 模块 |
| Object | 表示界面对象 |
| Property | 描述对象状态 |
id |
唯一标识对象 |
x、y |
绝对定位 |
anchors |
相对定位 |
| Expression | 属性值计算 |
| Binding | 属性之间自动联动 |
onClicked |
处理点击事件 |
console.log() |
输出调试信息 |
QML 界面的基本组成可以概括为:
text
QML 界面 = 对象 + 属性 + 对象关系 + 事件处理
而 QML 最重要的特点之一是:
text
属性绑定
通过属性绑定,可以让界面中的对象自动响应数据变化,从而减少大量手动更新界面的代码。
十七、快速复习清单
复习时可以重点回答下面的问题:
- QML 是什么类型的语言?
import有什么作用?- 什么是 QML 对象?
- 属性和
id有什么区别? parent表示什么?x、y与anchors有什么区别?- 如何让对象在父对象中居中?
- 什么是属性绑定?
- 修改被依赖属性后,绑定属性会发生什么?
- 如何处理按钮点击事件?
- 如何在 Qt Creator 中输出调试信息?
- 直接给绑定属性赋值可能产生什么影响?
十八、一句话记忆
QML 通过对象描述界面,通过属性设置状态,通过 anchors 设置位置,通过属性绑定实现自动联动,通过信号处理器响应用户操作。@TOC(QML 语法基础学习笔记)
QML 语法基础:从对象、属性到属性绑定
QML 是 Qt Quick 使用的一种声明式语言,主要用于快速构建图形界面。
相比传统的 C++ 界面开发,QML 的语法更加简洁直观。开发者只需要描述界面中有哪些对象、对象具有什么属性,以及对象之间有什么关系,就可以完成大部分界面开发工作。
本文整理 QML 中最基础、最常用的语法,包括:
import模块导入- QML 对象
- 属性与
id - 相对布局与绝对布局
- 注释
- 表达式
- 属性绑定
- 信号处理
- 调试输出
一、QML 是什么
QML,全称 Qt Modeling Language,是 Qt Quick 使用的声明式语言。
所谓声明式,可以简单理解为:
开发者主要描述"界面应该是什么样子",而不是一步一步告诉程序"应该怎样绘制界面"。
例如,下面的代码描述了一个红色矩形:
qml
Rectangle {
width: 200
height: 100
color: "red"
}
这段代码没有手动调用绘图函数,而是直接声明:
- 对象类型是
Rectangle - 宽度是
200 - 高度是
100 - 颜色是红色
QML 的主要特点包括:
- 语法简单,学习成本较低;
- 适合快速开发图形界面;
- 支持属性绑定;
- 支持动画和触摸交互;
- 可以与 JavaScript、C++ 配合使用;
- 适合桌面端、嵌入式设备和触摸屏应用。
二、import:导入模块
在使用 QML 组件之前,通常需要先导入组件所属的模块。
基本格式如下:
qml
import 模块名称 版本号
例如:
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Window
常见模块的作用如下:
| 模块 | 主要作用 |
|---|---|
QtQuick |
提供 Rectangle、Text、MouseArea 等基础类型 |
QtQuick.Controls |
提供 Button、Label、TextField 等控件 |
QtQuick.Window |
提供 Window 等窗口类型 |
QtQuick.Layouts |
提供 RowLayout、ColumnLayout 等布局类型 |
在部分 Qt 版本中,也可以写明版本号:
qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
如果没有导入组件所属的模块,程序可能会出现类似下面的错误:
text
Unknown component
或者:
text
Type Button unavailable
因此,可以把 import 理解为 C++ 中的 #include,但两者的具体机制并不完全相同。
三、QML 对象
QML 界面由一个个对象组成。
例如:
qml
Rectangle {
}
这里定义了一个 Rectangle 对象。
再例如:
qml
Button {
}
这里定义了一个 Button 对象。
可以将 QML 对象简单理解为 C++ 类创建出来的实例:
cpp
Rectangle rectangle;
Button button;
在 QML 中,对象通常采用下面的结构:
qml
对象类型 {
属性名: 属性值
子对象类型 {
属性名: 属性值
}
}
例如:
qml
Rectangle {
width: 300
height: 200
color: "lightgray"
Button {
text: "确定"
}
}
在这个例子中:
Rectangle是父对象;Button是Rectangle的子对象;- 按钮会显示在矩形内部。
四、属性与 id
4.1 什么是属性
属性用于描述对象的状态和外观。
例如:
qml
Rectangle {
width: 200
height: 100
color: "red"
opacity: 0.8
}
这里的属性包括:
width:宽度height:高度color:颜色opacity:透明度
按钮也有自己的属性:
qml
Button {
width: 120
height: 40
text: "确定"
font.pixelSize: 18
}
常见属性如下:
| 属性 | 作用 |
|---|---|
width |
设置宽度 |
height |
设置高度 |
x |
设置水平方向坐标 |
y |
设置垂直方向坐标 |
color |
设置颜色 |
text |
设置文本 |
visible |
控制是否可见 |
opacity |
设置透明度 |
font.pixelSize |
设置字体大小 |
4.2 id 的作用
id 是 QML 对象的唯一标识。
例如:
qml
Rectangle {
id: redRectangle
width: 200
height: 100
color: "red"
}
其他对象可以通过 redRectangle 访问这个矩形:
qml
Rectangle {
width: redRectangle.width / 2
height: 50
color: "blue"
}
需要注意:
- 同一个 QML 作用域中的
id不能重复; id不需要加引号;id通常使用小写字母开头;id是 QML 的特殊标识,不是普通属性;id创建后不能在运行期间修改。
正确写法:
qml
id: blueRectangle
错误写法:
qml
id: "blueRectangle"
五、父对象与子对象
QML 对象可以嵌套。
例如:
qml
Rectangle {
width: 400
height: 300
color: "lightgray"
Rectangle {
width: 100
height: 100
color: "red"
}
}
外层矩形是父对象,内层矩形是子对象。
子对象可以通过 parent 访问父对象:
qml
Rectangle {
width: parent.width / 2
height: parent.height / 2
color: "red"
}
这里表示:
- 子矩形宽度是父对象宽度的一半;
- 子矩形高度是父对象高度的一半。
六、QML 中的布局方式
QML 中常见的定位方式可以分为:
- 绝对定位;
- 相对定位;
- 布局管理器。
本节重点介绍前两种。
6.1 绝对定位
绝对定位通过 x 和 y 设置对象的位置。
qml
Rectangle {
width: 100
height: 100
x: 50
y: 80
color: "blue"
}
其中:
x表示对象左边距离父对象左边的距离;y表示对象顶部距离父对象顶部的距离。
QML 坐标系的原点通常位于父对象左上角:
text
(0, 0) ----------------> x
|
|
|
|
v
y
绝对定位的优点是简单直接,但当窗口大小发生变化时,对象的位置不会自动适配。
因此,绝对定位更适合:
- 固定尺寸的界面;
- 临时测试;
- 对位置要求非常明确的场景。
6.2 相对定位:anchors
anchors 可以让对象相对于父对象或其他对象进行定位。
居中显示
qml
Rectangle {
width: 100
height: 100
color: "red"
anchors.centerIn: parent
}
无论父窗口怎样变化,矩形都会保持居中。
水平居中
qml
anchors.horizontalCenter: parent.horizontalCenter
垂直居中
qml
anchors.verticalCenter: parent.verticalCenter
底部对齐
qml
anchors.bottom: parent.bottom
设置底部边距
qml
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
同时设置水平居中和底部对齐
qml
Button {
text: "确定"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
}
这样按钮会始终位于父对象底部,并保持水平居中。
6.3 常用 anchors 属性
| 属性 | 作用 |
|---|---|
anchors.left |
左边对齐 |
anchors.right |
右边对齐 |
anchors.top |
顶部对齐 |
anchors.bottom |
底部对齐 |
anchors.centerIn |
水平和垂直居中 |
anchors.horizontalCenter |
水平居中 |
anchors.verticalCenter |
垂直居中 |
anchors.fill |
填充目标对象 |
anchors.margins |
设置统一边距 |
anchors.leftMargin |
设置左边距 |
anchors.rightMargin |
设置右边距 |
anchors.topMargin |
设置顶部边距 |
anchors.bottomMargin |
设置底部边距 |
例如,让子对象填满父对象:
qml
Rectangle {
anchors.fill: parent
color: "lightblue"
}
设置统一边距:
qml
Rectangle {
anchors.fill: parent
anchors.margins: 20
color: "lightblue"
}
七、QML 注释
QML 的注释方式和 C、C++、JavaScript 类似。
7.1 单行注释
qml
// 这是一行注释
Rectangle {
width: 100 // 设置矩形宽度
}
7.2 多行注释
qml
/*
这是多行注释
可以连续注释多行内容
*/
例如:
qml
/*
Rectangle {
width: 100
height: 100
color: "gray"
}
*/
在 Qt Creator 中,通常可以使用快捷键:
text
Ctrl + /
对选中的代码进行注释或取消注释。
八、表达式
QML 属性值不仅可以是固定值,也可以是表达式。
例如:
qml
Rectangle {
width: parent.width / 2
height: parent.height / 2
}
这里使用了除法表达式。
常见运算符包括:
| 类型 | 运算符 |
|---|---|
| 加法 | + |
| 减法 | - |
| 乘法 | * |
| 除法 | / |
| 取余 | % |
| 大于 | > |
| 小于 | < |
| 等于 | === |
| 不等于 | !== |
| 逻辑与 | && |
| 逻辑或 | ` |
| 逻辑非 | ! |
例如:
qml
Rectangle {
width: parent.width - 40
height: width / 2
visible: parent.width > 300
}
也可以使用条件表达式:
qml
color: width > 200 ? "red" : "blue"
这表示:
- 当宽度大于
200时,颜色为红色; - 否则颜色为蓝色。
九、属性绑定
属性绑定是 QML 最重要的特性之一。
当一个属性使用了另一个属性的值时,QML 会自动建立绑定关系。
例如:
qml
Rectangle {
id: redRectangle
width: 200
height: 100
color: "red"
}
Rectangle {
id: blueRectangle
width: redRectangle.width / 2
height: 100
color: "blue"
}
这里蓝色矩形的宽度绑定到了红色矩形的宽度:
qml
width: redRectangle.width / 2
当红色矩形的宽度发生变化时,蓝色矩形的宽度也会自动变化。
例如:
qml
Button {
text: "增加宽度"
onClicked: {
redRectangle.width += 10
}
}
每次点击按钮:
- 红色矩形宽度增加
10; - 蓝色矩形的宽度自动重新计算;
- 不需要手动修改蓝色矩形。
这就是属性绑定的优势:
一个属性发生变化后,依赖它的属性会自动更新。
十、固定值与属性绑定的区别
固定值:
qml
width: 100
表示宽度始终是 100。
属性绑定:
qml
width: parent.width / 2
表示宽度会根据父对象宽度动态变化。
例如:
qml
Window {
width: 800
height: 600
Rectangle {
width: parent.width / 2
height: parent.height / 2
color: "red"
}
}
当窗口大小变化时,矩形会始终保持为窗口宽度和高度的一半。
十一、自定义属性
除了 QML 对象自带的属性,还可以通过 property 定义自定义属性。
基本格式如下:
qml
property 属性类型 属性名称: 默认值
例如:
qml
Rectangle {
property int count: 0
property string title: "QML 学习"
property bool enabledState: true
property real scaleValue: 1.5
}
常见属性类型如下:
| 类型 | 说明 |
|---|---|
int |
整数 |
real |
小数 |
double |
双精度小数 |
bool |
布尔值 |
string |
字符串 |
color |
颜色 |
url |
地址 |
var |
任意类型 |
按钮点击时可以修改自定义属性:
qml
Button {
text: "增加"
onClicked: {
count += 1
}
}
十二、信号与事件处理
QML 控件可以通过信号处理器响应用户操作。
例如,按钮具有 clicked 信号,对应的处理器是:
qml
onClicked
完整示例:
qml
Button {
text: "点击按钮"
onClicked: {
console.log("按钮被点击")
}
}
常见事件处理器包括:
| 处理器 | 作用 |
|---|---|
onClicked |
鼠标点击 |
onPressed |
鼠标按下 |
onReleased |
鼠标释放 |
onDoubleClicked |
鼠标双击 |
onWidthChanged |
宽度发生变化 |
onHeightChanged |
高度发生变化 |
onTextChanged |
文本发生变化 |
例如:
qml
Rectangle {
width: 100
onWidthChanged: {
console.log("当前宽度:", width)
}
}
十三、QML 调试输出
QML 可以使用 console 输出调试信息。
普通输出
qml
console.log("程序运行")
调试信息
qml
console.debug("调试信息")
警告信息
qml
console.warn("警告信息")
错误信息
qml
console.error("错误信息")
也可以一次输出多个值:
qml
console.log("矩形坐标:", blueRectangle.x, blueRectangle.y)
在 Qt Creator 中,可以在下面的位置查看输出:
text
Application Output
也就是"应用程序输出"窗口。
十四、完整示例:矩形、按钮与属性绑定
下面通过一个完整案例练习本节涉及的主要语法。
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Window
Window {
id: rootWindow
width: 800
height: 600
visible: true
title: "QML 语法基础示例"
Rectangle {
id: redRectangle
width: 200
height: 120
color: "red"
radius: 8
anchors.centerIn: parent
}
Rectangle {
id: blueRectangle
// 蓝色矩形的宽度绑定到红色矩形宽度的一半
width: redRectangle.width / 2
height: 80
color: "blue"
radius: 8
x: 30
y: 30
}
Button {
id: addButton
text: "增加宽度"
font.pixelSize: 16
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.leftMargin: 20
anchors.bottomMargin: 20
onClicked: {
redRectangle.width += 10
console.log("增加按钮被点击")
console.log("红色矩形宽度:", redRectangle.width)
console.log("蓝色矩形宽度:", blueRectangle.width)
}
}
Button {
id: subtractButton
text: "减小宽度"
font.pixelSize: 16
anchors.left: addButton.right
anchors.bottom: parent.bottom
anchors.leftMargin: 10
anchors.bottomMargin: 20
onClicked: {
if (redRectangle.width > 50) {
redRectangle.width -= 10
}
console.log("减小按钮被点击")
console.log("红色矩形宽度:", redRectangle.width)
console.log("蓝色矩形宽度:", blueRectangle.width)
}
}
Button {
id: moveButton
text: "移动蓝色矩形"
font.pixelSize: 16
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 20
anchors.bottomMargin: 20
onClicked: {
blueRectangle.x += 16
console.log("蓝色矩形当前 x 坐标:", blueRectangle.x)
}
}
}
这个示例包含:
- 使用
import导入模块; - 创建
Window、Rectangle和Button对象; - 使用
id标识对象; - 使用
width、height、color等属性; - 使用
anchors进行相对定位; - 使用
x和y进行绝对定位; - 使用表达式计算属性;
- 使用属性绑定联动两个矩形;
- 使用
onClicked处理按钮点击; - 使用
console.log()输出调试信息。
十五、容易混淆的知识点
15.1 id 不是普通属性
qml
id: redRectangle
id 是对象的特殊标识,不能像普通属性一样动态修改。
15.2 属性绑定会自动更新
qml
width: redRectangle.width / 2
只要 redRectangle.width 变化,这里的宽度就会自动重新计算。
15.3 赋值可能破坏原来的绑定
假设最开始存在属性绑定:
qml
width: redRectangle.width / 2
如果之后在 JavaScript 代码中直接赋值:
qml
blueRectangle.width = 300
原来的绑定关系通常会被新的固定值替代。
此后红色矩形宽度变化时,蓝色矩形宽度可能不再自动更新。
因此,开发时需要区分:
- 声明属性绑定;
- 在事件处理器中直接赋值。
15.4 anchors 与 x、y 不要随意混用
例如,一个对象已经设置:
qml
anchors.horizontalCenter: parent.horizontalCenter
这时再设置:
qml
x: 100
可能无法得到预期结果,因为 anchors 正在负责对象的水平位置。
一般建议:
- 使用
anchors时,让anchors管理对应方向的位置; - 使用
x、y时,不要再对同一方向设置锚点。
15.5 Rectangle 与 Button 所属模块不同
Rectangle 通常来自:
qml
import QtQuick
Button 通常来自:
qml
import QtQuick.Controls
因此,只导入 QtQuick 时,不一定能直接使用 Button。
十六、本节知识总结
QML 的基础语法可以归纳为下面几个关键词:
| 关键词 | 作用 |
|---|---|
import |
导入 QML 模块 |
| Object | 表示界面对象 |
| Property | 描述对象状态 |
id |
唯一标识对象 |
x、y |
绝对定位 |
anchors |
相对定位 |
| Expression | 属性值计算 |
| Binding | 属性之间自动联动 |
onClicked |
处理点击事件 |
console.log() |
输出调试信息 |
QML 界面的基本组成可以概括为:
text
QML 界面 = 对象 + 属性 + 对象关系 + 事件处理
而 QML 最重要的特点之一是:
text
属性绑定
通过属性绑定,可以让界面中的对象自动响应数据变化,从而减少大量手动更新界面的代码。
十七、快速复习清单
复习时可以重点回答下面的问题:
- QML 是什么类型的语言?
import有什么作用?- 什么是 QML 对象?
- 属性和
id有什么区别? parent表示什么?x、y与anchors有什么区别?- 如何让对象在父对象中居中?
- 什么是属性绑定?
- 修改被依赖属性后,绑定属性会发生什么?
- 如何处理按钮点击事件?
- 如何在 Qt Creator 中输出调试信息?
- 直接给绑定属性赋值可能产生什么影响?
十八、一句话记忆
QML 通过对象描述界面,通过属性设置状态,通过 anchors 设置位置,通过属性绑定实现自动联动,通过信号处理器响应用户操作。@TOC(QML 语法基础学习笔记)
QML 语法基础:从对象、属性到属性绑定
QML 是 Qt Quick 使用的一种声明式语言,主要用于快速构建图形界面。
相比传统的 C++ 界面开发,QML 的语法更加简洁直观。开发者只需要描述界面中有哪些对象、对象具有什么属性,以及对象之间有什么关系,就可以完成大部分界面开发工作。
本文整理 QML 中最基础、最常用的语法,包括:
import模块导入- QML 对象
- 属性与
id - 相对布局与绝对布局
- 注释
- 表达式
- 属性绑定
- 信号处理
- 调试输出
一、QML 是什么
QML,全称 Qt Modeling Language,是 Qt Quick 使用的声明式语言。
所谓声明式,可以简单理解为:
开发者主要描述"界面应该是什么样子",而不是一步一步告诉程序"应该怎样绘制界面"。
例如,下面的代码描述了一个红色矩形:
qml
Rectangle {
width: 200
height: 100
color: "red"
}
这段代码没有手动调用绘图函数,而是直接声明:
- 对象类型是
Rectangle - 宽度是
200 - 高度是
100 - 颜色是红色
QML 的主要特点包括:
- 语法简单,学习成本较低;
- 适合快速开发图形界面;
- 支持属性绑定;
- 支持动画和触摸交互;
- 可以与 JavaScript、C++ 配合使用;
- 适合桌面端、嵌入式设备和触摸屏应用。
二、import:导入模块
在使用 QML 组件之前,通常需要先导入组件所属的模块。
基本格式如下:
qml
import 模块名称 版本号
例如:
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Window
常见模块的作用如下:
| 模块 | 主要作用 |
|---|---|
QtQuick |
提供 Rectangle、Text、MouseArea 等基础类型 |
QtQuick.Controls |
提供 Button、Label、TextField 等控件 |
QtQuick.Window |
提供 Window 等窗口类型 |
QtQuick.Layouts |
提供 RowLayout、ColumnLayout 等布局类型 |
在部分 Qt 版本中,也可以写明版本号:
qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
如果没有导入组件所属的模块,程序可能会出现类似下面的错误:
text
Unknown component
或者:
text
Type Button unavailable
因此,可以把 import 理解为 C++ 中的 #include,但两者的具体机制并不完全相同。
三、QML 对象
QML 界面由一个个对象组成。
例如:
qml
Rectangle {
}
这里定义了一个 Rectangle 对象。
再例如:
qml
Button {
}
这里定义了一个 Button 对象。
可以将 QML 对象简单理解为 C++ 类创建出来的实例:
cpp
Rectangle rectangle;
Button button;
在 QML 中,对象通常采用下面的结构:
qml
对象类型 {
属性名: 属性值
子对象类型 {
属性名: 属性值
}
}
例如:
qml
Rectangle {
width: 300
height: 200
color: "lightgray"
Button {
text: "确定"
}
}
在这个例子中:
Rectangle是父对象;Button是Rectangle的子对象;- 按钮会显示在矩形内部。
四、属性与 id
4.1 什么是属性
属性用于描述对象的状态和外观。
例如:
qml
Rectangle {
width: 200
height: 100
color: "red"
opacity: 0.8
}
这里的属性包括:
width:宽度height:高度color:颜色opacity:透明度
按钮也有自己的属性:
qml
Button {
width: 120
height: 40
text: "确定"
font.pixelSize: 18
}
常见属性如下:
| 属性 | 作用 |
|---|---|
width |
设置宽度 |
height |
设置高度 |
x |
设置水平方向坐标 |
y |
设置垂直方向坐标 |
color |
设置颜色 |
text |
设置文本 |
visible |
控制是否可见 |
opacity |
设置透明度 |
font.pixelSize |
设置字体大小 |
4.2 id 的作用
id 是 QML 对象的唯一标识。
例如:
qml
Rectangle {
id: redRectangle
width: 200
height: 100
color: "red"
}
其他对象可以通过 redRectangle 访问这个矩形:
qml
Rectangle {
width: redRectangle.width / 2
height: 50
color: "blue"
}
需要注意:
- 同一个 QML 作用域中的
id不能重复; id不需要加引号;id通常使用小写字母开头;id是 QML 的特殊标识,不是普通属性;id创建后不能在运行期间修改。
正确写法:
qml
id: blueRectangle
错误写法:
qml
id: "blueRectangle"
五、父对象与子对象
QML 对象可以嵌套。
例如:
qml
Rectangle {
width: 400
height: 300
color: "lightgray"
Rectangle {
width: 100
height: 100
color: "red"
}
}
外层矩形是父对象,内层矩形是子对象。
子对象可以通过 parent 访问父对象:
qml
Rectangle {
width: parent.width / 2
height: parent.height / 2
color: "red"
}
这里表示:
- 子矩形宽度是父对象宽度的一半;
- 子矩形高度是父对象高度的一半。
六、QML 中的布局方式
QML 中常见的定位方式可以分为:
- 绝对定位;
- 相对定位;
- 布局管理器。
本节重点介绍前两种。
6.1 绝对定位
绝对定位通过 x 和 y 设置对象的位置。
qml
Rectangle {
width: 100
height: 100
x: 50
y: 80
color: "blue"
}
其中:
x表示对象左边距离父对象左边的距离;y表示对象顶部距离父对象顶部的距离。
QML 坐标系的原点通常位于父对象左上角:
text
(0, 0) ----------------> x
|
|
|
|
v
y
绝对定位的优点是简单直接,但当窗口大小发生变化时,对象的位置不会自动适配。
因此,绝对定位更适合:
- 固定尺寸的界面;
- 临时测试;
- 对位置要求非常明确的场景。
6.2 相对定位:anchors
anchors 可以让对象相对于父对象或其他对象进行定位。
居中显示
qml
Rectangle {
width: 100
height: 100
color: "red"
anchors.centerIn: parent
}
无论父窗口怎样变化,矩形都会保持居中。
水平居中
qml
anchors.horizontalCenter: parent.horizontalCenter
垂直居中
qml
anchors.verticalCenter: parent.verticalCenter
底部对齐
qml
anchors.bottom: parent.bottom
设置底部边距
qml
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
同时设置水平居中和底部对齐
qml
Button {
text: "确定"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
}
这样按钮会始终位于父对象底部,并保持水平居中。
6.3 常用 anchors 属性
| 属性 | 作用 |
|---|---|
anchors.left |
左边对齐 |
anchors.right |
右边对齐 |
anchors.top |
顶部对齐 |
anchors.bottom |
底部对齐 |
anchors.centerIn |
水平和垂直居中 |
anchors.horizontalCenter |
水平居中 |
anchors.verticalCenter |
垂直居中 |
anchors.fill |
填充目标对象 |
anchors.margins |
设置统一边距 |
anchors.leftMargin |
设置左边距 |
anchors.rightMargin |
设置右边距 |
anchors.topMargin |
设置顶部边距 |
anchors.bottomMargin |
设置底部边距 |
例如,让子对象填满父对象:
qml
Rectangle {
anchors.fill: parent
color: "lightblue"
}
设置统一边距:
qml
Rectangle {
anchors.fill: parent
anchors.margins: 20
color: "lightblue"
}
七、QML 注释
QML 的注释方式和 C、C++、JavaScript 类似。
7.1 单行注释
qml
// 这是一行注释
Rectangle {
width: 100 // 设置矩形宽度
}
7.2 多行注释
qml
/*
这是多行注释
可以连续注释多行内容
*/
例如:
qml
/*
Rectangle {
width: 100
height: 100
color: "gray"
}
*/
在 Qt Creator 中,通常可以使用快捷键:
text
Ctrl + /
对选中的代码进行注释或取消注释。
八、表达式
QML 属性值不仅可以是固定值,也可以是表达式。
例如:
qml
Rectangle {
width: parent.width / 2
height: parent.height / 2
}
这里使用了除法表达式。
常见运算符包括:
| 类型 | 运算符 |
|---|---|
| 加法 | + |
| 减法 | - |
| 乘法 | * |
| 除法 | / |
| 取余 | % |
| 大于 | > |
| 小于 | < |
| 等于 | === |
| 不等于 | !== |
| 逻辑与 | && |
| 逻辑或 | ` |
| 逻辑非 | ! |
例如:
qml
Rectangle {
width: parent.width - 40
height: width / 2
visible: parent.width > 300
}
也可以使用条件表达式:
qml
color: width > 200 ? "red" : "blue"
这表示:
- 当宽度大于
200时,颜色为红色; - 否则颜色为蓝色。
九、属性绑定
属性绑定是 QML 最重要的特性之一。
当一个属性使用了另一个属性的值时,QML 会自动建立绑定关系。
例如:
qml
Rectangle {
id: redRectangle
width: 200
height: 100
color: "red"
}
Rectangle {
id: blueRectangle
width: redRectangle.width / 2
height: 100
color: "blue"
}
这里蓝色矩形的宽度绑定到了红色矩形的宽度:
qml
width: redRectangle.width / 2
当红色矩形的宽度发生变化时,蓝色矩形的宽度也会自动变化。
例如:
qml
Button {
text: "增加宽度"
onClicked: {
redRectangle.width += 10
}
}
每次点击按钮:
- 红色矩形宽度增加
10; - 蓝色矩形的宽度自动重新计算;
- 不需要手动修改蓝色矩形。
这就是属性绑定的优势:
一个属性发生变化后,依赖它的属性会自动更新。
十、固定值与属性绑定的区别
固定值:
qml
width: 100
表示宽度始终是 100。
属性绑定:
qml
width: parent.width / 2
表示宽度会根据父对象宽度动态变化。
例如:
qml
Window {
width: 800
height: 600
Rectangle {
width: parent.width / 2
height: parent.height / 2
color: "red"
}
}
当窗口大小变化时,矩形会始终保持为窗口宽度和高度的一半。
十一、自定义属性
除了 QML 对象自带的属性,还可以通过 property 定义自定义属性。
基本格式如下:
qml
property 属性类型 属性名称: 默认值
例如:
qml
Rectangle {
property int count: 0
property string title: "QML 学习"
property bool enabledState: true
property real scaleValue: 1.5
}
常见属性类型如下:
| 类型 | 说明 |
|---|---|
int |
整数 |
real |
小数 |
double |
双精度小数 |
bool |
布尔值 |
string |
字符串 |
color |
颜色 |
url |
地址 |
var |
任意类型 |
按钮点击时可以修改自定义属性:
qml
Button {
text: "增加"
onClicked: {
count += 1
}
}
十二、信号与事件处理
QML 控件可以通过信号处理器响应用户操作。
例如,按钮具有 clicked 信号,对应的处理器是:
qml
onClicked
完整示例:
qml
Button {
text: "点击按钮"
onClicked: {
console.log("按钮被点击")
}
}
常见事件处理器包括:
| 处理器 | 作用 |
|---|---|
onClicked |
鼠标点击 |
onPressed |
鼠标按下 |
onReleased |
鼠标释放 |
onDoubleClicked |
鼠标双击 |
onWidthChanged |
宽度发生变化 |
onHeightChanged |
高度发生变化 |
onTextChanged |
文本发生变化 |
例如:
qml
Rectangle {
width: 100
onWidthChanged: {
console.log("当前宽度:", width)
}
}
十三、QML 调试输出
QML 可以使用 console 输出调试信息。
普通输出
qml
console.log("程序运行")
调试信息
qml
console.debug("调试信息")
警告信息
qml
console.warn("警告信息")
错误信息
qml
console.error("错误信息")
也可以一次输出多个值:
qml
console.log("矩形坐标:", blueRectangle.x, blueRectangle.y)
在 Qt Creator 中,可以在下面的位置查看输出:
text
Application Output
也就是"应用程序输出"窗口。
十四、完整示例:矩形、按钮与属性绑定
下面通过一个完整案例练习本节涉及的主要语法。
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Window
Window {
id: rootWindow
width: 800
height: 600
visible: true
title: "QML 语法基础示例"
Rectangle {
id: redRectangle
width: 200
height: 120
color: "red"
radius: 8
anchors.centerIn: parent
}
Rectangle {
id: blueRectangle
// 蓝色矩形的宽度绑定到红色矩形宽度的一半
width: redRectangle.width / 2
height: 80
color: "blue"
radius: 8
x: 30
y: 30
}
Button {
id: addButton
text: "增加宽度"
font.pixelSize: 16
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.leftMargin: 20
anchors.bottomMargin: 20
onClicked: {
redRectangle.width += 10
console.log("增加按钮被点击")
console.log("红色矩形宽度:", redRectangle.width)
console.log("蓝色矩形宽度:", blueRectangle.width)
}
}
Button {
id: subtractButton
text: "减小宽度"
font.pixelSize: 16
anchors.left: addButton.right
anchors.bottom: parent.bottom
anchors.leftMargin: 10
anchors.bottomMargin: 20
onClicked: {
if (redRectangle.width > 50) {
redRectangle.width -= 10
}
console.log("减小按钮被点击")
console.log("红色矩形宽度:", redRectangle.width)
console.log("蓝色矩形宽度:", blueRectangle.width)
}
}
Button {
id: moveButton
text: "移动蓝色矩形"
font.pixelSize: 16
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 20
anchors.bottomMargin: 20
onClicked: {
blueRectangle.x += 16
console.log("蓝色矩形当前 x 坐标:", blueRectangle.x)
}
}
}
这个示例包含:
- 使用
import导入模块; - 创建
Window、Rectangle和Button对象; - 使用
id标识对象; - 使用
width、height、color等属性; - 使用
anchors进行相对定位; - 使用
x和y进行绝对定位; - 使用表达式计算属性;
- 使用属性绑定联动两个矩形;
- 使用
onClicked处理按钮点击; - 使用
console.log()输出调试信息。
十五、容易混淆的知识点
15.1 id 不是普通属性
qml
id: redRectangle
id 是对象的特殊标识,不能像普通属性一样动态修改。
15.2 属性绑定会自动更新
qml
width: redRectangle.width / 2
只要 redRectangle.width 变化,这里的宽度就会自动重新计算。
15.3 赋值可能破坏原来的绑定
假设最开始存在属性绑定:
qml
width: redRectangle.width / 2
如果之后在 JavaScript 代码中直接赋值:
qml
blueRectangle.width = 300
原来的绑定关系通常会被新的固定值替代。
此后红色矩形宽度变化时,蓝色矩形宽度可能不再自动更新。
因此,开发时需要区分:
- 声明属性绑定;
- 在事件处理器中直接赋值。
15.4 anchors 与 x、y 不要随意混用
例如,一个对象已经设置:
qml
anchors.horizontalCenter: parent.horizontalCenter
这时再设置:
qml
x: 100
可能无法得到预期结果,因为 anchors 正在负责对象的水平位置。
一般建议:
- 使用
anchors时,让anchors管理对应方向的位置; - 使用
x、y时,不要再对同一方向设置锚点。
15.5 Rectangle 与 Button 所属模块不同
Rectangle 通常来自:
qml
import QtQuick
Button 通常来自:
qml
import QtQuick.Controls
因此,只导入 QtQuick 时,不一定能直接使用 Button。
十六、本节知识总结
QML 的基础语法可以归纳为下面几个关键词:
| 关键词 | 作用 |
|---|---|
import |
导入 QML 模块 |
| Object | 表示界面对象 |
| Property | 描述对象状态 |
id |
唯一标识对象 |
x、y |
绝对定位 |
anchors |
相对定位 |
| Expression | 属性值计算 |
| Binding | 属性之间自动联动 |
onClicked |
处理点击事件 |
console.log() |
输出调试信息 |
QML 界面的基本组成可以概括为:
text
QML 界面 = 对象 + 属性 + 对象关系 + 事件处理
而 QML 最重要的特点之一是:
text
属性绑定
通过属性绑定,可以让界面中的对象自动响应数据变化,从而减少大量手动更新界面的代码。
十七、快速复习清单
复习时可以重点回答下面的问题:
- QML 是什么类型的语言?
import有什么作用?- 什么是 QML 对象?
- 属性和
id有什么区别? parent表示什么?x、y与anchors有什么区别?- 如何让对象在父对象中居中?
- 什么是属性绑定?
- 修改被依赖属性后,绑定属性会发生什么?
- 如何处理按钮点击事件?
- 如何在 Qt Creator 中输出调试信息?
- 直接给绑定属性赋值可能产生什么影响?
十八、一句话记忆
QML 通过对象描述界面,通过属性设置状态,通过 anchors 设置位置,通过属性绑定实现自动联动,通过信号处理器响应用户操作。@TOC(QML 语法基础学习笔记)
QML 语法基础:从对象、属性到属性绑定
QML 是 Qt Quick 使用的一种声明式语言,主要用于快速构建图形界面。
相比传统的 C++ 界面开发,QML 的语法更加简洁直观。开发者只需要描述界面中有哪些对象、对象具有什么属性,以及对象之间有什么关系,就可以完成大部分界面开发工作。
本文整理 QML 中最基础、最常用的语法,包括:
import模块导入- QML 对象
- 属性与
id - 相对布局与绝对布局
- 注释
- 表达式
- 属性绑定
- 信号处理
- 调试输出
一、QML 是什么
QML,全称 Qt Modeling Language,是 Qt Quick 使用的声明式语言。
所谓声明式,可以简单理解为:
开发者主要描述"界面应该是什么样子",而不是一步一步告诉程序"应该怎样绘制界面"。
例如,下面的代码描述了一个红色矩形:
qml
Rectangle {
width: 200
height: 100
color: "red"
}
这段代码没有手动调用绘图函数,而是直接声明:
- 对象类型是
Rectangle - 宽度是
200 - 高度是
100 - 颜色是红色
QML 的主要特点包括:
- 语法简单,学习成本较低;
- 适合快速开发图形界面;
- 支持属性绑定;
- 支持动画和触摸交互;
- 可以与 JavaScript、C++ 配合使用;
- 适合桌面端、嵌入式设备和触摸屏应用。
二、import:导入模块
在使用 QML 组件之前,通常需要先导入组件所属的模块。
基本格式如下:
qml
import 模块名称 版本号
例如:
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Window
常见模块的作用如下:
| 模块 | 主要作用 |
|---|---|
QtQuick |
提供 Rectangle、Text、MouseArea 等基础类型 |
QtQuick.Controls |
提供 Button、Label、TextField 等控件 |
QtQuick.Window |
提供 Window 等窗口类型 |
QtQuick.Layouts |
提供 RowLayout、ColumnLayout 等布局类型 |
在部分 Qt 版本中,也可以写明版本号:
qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
如果没有导入组件所属的模块,程序可能会出现类似下面的错误:
text
Unknown component
或者:
text
Type Button unavailable
因此,可以把 import 理解为 C++ 中的 #include,但两者的具体机制并不完全相同。
三、QML 对象
QML 界面由一个个对象组成。
例如:
qml
Rectangle {
}
这里定义了一个 Rectangle 对象。
再例如:
qml
Button {
}
这里定义了一个 Button 对象。
可以将 QML 对象简单理解为 C++ 类创建出来的实例:
cpp
Rectangle rectangle;
Button button;
在 QML 中,对象通常采用下面的结构:
qml
对象类型 {
属性名: 属性值
子对象类型 {
属性名: 属性值
}
}
例如:
qml
Rectangle {
width: 300
height: 200
color: "lightgray"
Button {
text: "确定"
}
}
在这个例子中:
Rectangle是父对象;Button是Rectangle的子对象;- 按钮会显示在矩形内部。
四、属性与 id
4.1 什么是属性
属性用于描述对象的状态和外观。
例如:
qml
Rectangle {
width: 200
height: 100
color: "red"
opacity: 0.8
}
这里的属性包括:
width:宽度height:高度color:颜色opacity:透明度
按钮也有自己的属性:
qml
Button {
width: 120
height: 40
text: "确定"
font.pixelSize: 18
}
常见属性如下:
| 属性 | 作用 |
|---|---|
width |
设置宽度 |
height |
设置高度 |
x |
设置水平方向坐标 |
y |
设置垂直方向坐标 |
color |
设置颜色 |
text |
设置文本 |
visible |
控制是否可见 |
opacity |
设置透明度 |
font.pixelSize |
设置字体大小 |
4.2 id 的作用
id 是 QML 对象的唯一标识。
例如:
qml
Rectangle {
id: redRectangle
width: 200
height: 100
color: "red"
}
其他对象可以通过 redRectangle 访问这个矩形:
qml
Rectangle {
width: redRectangle.width / 2
height: 50
color: "blue"
}
需要注意:
- 同一个 QML 作用域中的
id不能重复; id不需要加引号;id通常使用小写字母开头;id是 QML 的特殊标识,不是普通属性;id创建后不能在运行期间修改。
正确写法:
qml
id: blueRectangle
错误写法:
qml
id: "blueRectangle"
五、父对象与子对象
QML 对象可以嵌套。
例如:
qml
Rectangle {
width: 400
height: 300
color: "lightgray"
Rectangle {
width: 100
height: 100
color: "red"
}
}
外层矩形是父对象,内层矩形是子对象。
子对象可以通过 parent 访问父对象:
qml
Rectangle {
width: parent.width / 2
height: parent.height / 2
color: "red"
}
这里表示:
- 子矩形宽度是父对象宽度的一半;
- 子矩形高度是父对象高度的一半。
六、QML 中的布局方式
QML 中常见的定位方式可以分为:
- 绝对定位;
- 相对定位;
- 布局管理器。
本节重点介绍前两种。
6.1 绝对定位
绝对定位通过 x 和 y 设置对象的位置。
qml
Rectangle {
width: 100
height: 100
x: 50
y: 80
color: "blue"
}
其中:
x表示对象左边距离父对象左边的距离;y表示对象顶部距离父对象顶部的距离。
QML 坐标系的原点通常位于父对象左上角:
text
(0, 0) ----------------> x
|
|
|
|
v
y
绝对定位的优点是简单直接,但当窗口大小发生变化时,对象的位置不会自动适配。
因此,绝对定位更适合:
- 固定尺寸的界面;
- 临时测试;
- 对位置要求非常明确的场景。
6.2 相对定位:anchors
anchors 可以让对象相对于父对象或其他对象进行定位。
居中显示
qml
Rectangle {
width: 100
height: 100
color: "red"
anchors.centerIn: parent
}
无论父窗口怎样变化,矩形都会保持居中。
水平居中
qml
anchors.horizontalCenter: parent.horizontalCenter
垂直居中
qml
anchors.verticalCenter: parent.verticalCenter
底部对齐
qml
anchors.bottom: parent.bottom
设置底部边距
qml
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
同时设置水平居中和底部对齐
qml
Button {
text: "确定"
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
}
这样按钮会始终位于父对象底部,并保持水平居中。
6.3 常用 anchors 属性
| 属性 | 作用 |
|---|---|
anchors.left |
左边对齐 |
anchors.right |
右边对齐 |
anchors.top |
顶部对齐 |
anchors.bottom |
底部对齐 |
anchors.centerIn |
水平和垂直居中 |
anchors.horizontalCenter |
水平居中 |
anchors.verticalCenter |
垂直居中 |
anchors.fill |
填充目标对象 |
anchors.margins |
设置统一边距 |
anchors.leftMargin |
设置左边距 |
anchors.rightMargin |
设置右边距 |
anchors.topMargin |
设置顶部边距 |
anchors.bottomMargin |
设置底部边距 |
例如,让子对象填满父对象:
qml
Rectangle {
anchors.fill: parent
color: "lightblue"
}
设置统一边距:
qml
Rectangle {
anchors.fill: parent
anchors.margins: 20
color: "lightblue"
}
七、QML 注释
QML 的注释方式和 C、C++、JavaScript 类似。
7.1 单行注释
qml
// 这是一行注释
Rectangle {
width: 100 // 设置矩形宽度
}
7.2 多行注释
qml
/*
这是多行注释
可以连续注释多行内容
*/
例如:
qml
/*
Rectangle {
width: 100
height: 100
color: "gray"
}
*/
在 Qt Creator 中,通常可以使用快捷键:
text
Ctrl + /
对选中的代码进行注释或取消注释。
八、表达式
QML 属性值不仅可以是固定值,也可以是表达式。
例如:
qml
Rectangle {
width: parent.width / 2
height: parent.height / 2
}
这里使用了除法表达式。
常见运算符包括:
| 类型 | 运算符 |
|---|---|
| 加法 | + |
| 减法 | - |
| 乘法 | * |
| 除法 | / |
| 取余 | % |
| 大于 | > |
| 小于 | < |
| 等于 | === |
| 不等于 | !== |
| 逻辑与 | && |
| 逻辑或 | ` |
| 逻辑非 | ! |
例如:
qml
Rectangle {
width: parent.width - 40
height: width / 2
visible: parent.width > 300
}
也可以使用条件表达式:
qml
color: width > 200 ? "red" : "blue"
这表示:
- 当宽度大于
200时,颜色为红色; - 否则颜色为蓝色。
九、属性绑定
属性绑定是 QML 最重要的特性之一。
当一个属性使用了另一个属性的值时,QML 会自动建立绑定关系。
例如:
qml
Rectangle {
id: redRectangle
width: 200
height: 100
color: "red"
}
Rectangle {
id: blueRectangle
width: redRectangle.width / 2
height: 100
color: "blue"
}
这里蓝色矩形的宽度绑定到了红色矩形的宽度:
qml
width: redRectangle.width / 2
当红色矩形的宽度发生变化时,蓝色矩形的宽度也会自动变化。
例如:
qml
Button {
text: "增加宽度"
onClicked: {
redRectangle.width += 10
}
}
每次点击按钮:
- 红色矩形宽度增加
10; - 蓝色矩形的宽度自动重新计算;
- 不需要手动修改蓝色矩形。
这就是属性绑定的优势:
一个属性发生变化后,依赖它的属性会自动更新。
十、固定值与属性绑定的区别
固定值:
qml
width: 100
表示宽度始终是 100。
属性绑定:
qml
width: parent.width / 2
表示宽度会根据父对象宽度动态变化。
例如:
qml
Window {
width: 800
height: 600
Rectangle {
width: parent.width / 2
height: parent.height / 2
color: "red"
}
}
当窗口大小变化时,矩形会始终保持为窗口宽度和高度的一半。
十一、自定义属性
除了 QML 对象自带的属性,还可以通过 property 定义自定义属性。
基本格式如下:
qml
property 属性类型 属性名称: 默认值
例如:
qml
Rectangle {
property int count: 0
property string title: "QML 学习"
property bool enabledState: true
property real scaleValue: 1.5
}
常见属性类型如下:
| 类型 | 说明 |
|---|---|
int |
整数 |
real |
小数 |
double |
双精度小数 |
bool |
布尔值 |
string |
字符串 |
color |
颜色 |
url |
地址 |
var |
任意类型 |
按钮点击时可以修改自定义属性:
qml
Button {
text: "增加"
onClicked: {
count += 1
}
}
十二、信号与事件处理
QML 控件可以通过信号处理器响应用户操作。
例如,按钮具有 clicked 信号,对应的处理器是:
qml
onClicked
完整示例:
qml
Button {
text: "点击按钮"
onClicked: {
console.log("按钮被点击")
}
}
常见事件处理器包括:
| 处理器 | 作用 |
|---|---|
onClicked |
鼠标点击 |
onPressed |
鼠标按下 |
onReleased |
鼠标释放 |
onDoubleClicked |
鼠标双击 |
onWidthChanged |
宽度发生变化 |
onHeightChanged |
高度发生变化 |
onTextChanged |
文本发生变化 |
例如:
qml
Rectangle {
width: 100
onWidthChanged: {
console.log("当前宽度:", width)
}
}
十三、QML 调试输出
QML 可以使用 console 输出调试信息。
普通输出
qml
console.log("程序运行")
调试信息
qml
console.debug("调试信息")
警告信息
qml
console.warn("警告信息")
错误信息
qml
console.error("错误信息")
也可以一次输出多个值:
qml
console.log("矩形坐标:", blueRectangle.x, blueRectangle.y)
在 Qt Creator 中,可以在下面的位置查看输出:
text
Application Output
也就是"应用程序输出"窗口。
十四、完整示例:矩形、按钮与属性绑定
下面通过一个完整案例练习本节涉及的主要语法。
qml
import QtQuick
import QtQuick.Controls
import QtQuick.Window
Window {
id: rootWindow
width: 800
height: 600
visible: true
title: "QML 语法基础示例"
Rectangle {
id: redRectangle
width: 200
height: 120
color: "red"
radius: 8
anchors.centerIn: parent
}
Rectangle {
id: blueRectangle
// 蓝色矩形的宽度绑定到红色矩形宽度的一半
width: redRectangle.width / 2
height: 80
color: "blue"
radius: 8
x: 30
y: 30
}
Button {
id: addButton
text: "增加宽度"
font.pixelSize: 16
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.leftMargin: 20
anchors.bottomMargin: 20
onClicked: {
redRectangle.width += 10
console.log("增加按钮被点击")
console.log("红色矩形宽度:", redRectangle.width)
console.log("蓝色矩形宽度:", blueRectangle.width)
}
}
Button {
id: subtractButton
text: "减小宽度"
font.pixelSize: 16
anchors.left: addButton.right
anchors.bottom: parent.bottom
anchors.leftMargin: 10
anchors.bottomMargin: 20
onClicked: {
if (redRectangle.width > 50) {
redRectangle.width -= 10
}
console.log("减小按钮被点击")
console.log("红色矩形宽度:", redRectangle.width)
console.log("蓝色矩形宽度:", blueRectangle.width)
}
}
Button {
id: moveButton
text: "移动蓝色矩形"
font.pixelSize: 16
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 20
anchors.bottomMargin: 20
onClicked: {
blueRectangle.x += 16
console.log("蓝色矩形当前 x 坐标:", blueRectangle.x)
}
}
}
这个示例包含:
- 使用
import导入模块; - 创建
Window、Rectangle和Button对象; - 使用
id标识对象; - 使用
width、height、color等属性; - 使用
anchors进行相对定位; - 使用
x和y进行绝对定位; - 使用表达式计算属性;
- 使用属性绑定联动两个矩形;
- 使用
onClicked处理按钮点击; - 使用
console.log()输出调试信息。
十五、容易混淆的知识点
15.1 id 不是普通属性
qml
id: redRectangle
id 是对象的特殊标识,不能像普通属性一样动态修改。
15.2 属性绑定会自动更新
qml
width: redRectangle.width / 2
只要 redRectangle.width 变化,这里的宽度就会自动重新计算。
15.3 赋值可能破坏原来的绑定
假设最开始存在属性绑定:
qml
width: redRectangle.width / 2
如果之后在 JavaScript 代码中直接赋值:
qml
blueRectangle.width = 300
原来的绑定关系通常会被新的固定值替代。
此后红色矩形宽度变化时,蓝色矩形宽度可能不再自动更新。
因此,开发时需要区分:
- 声明属性绑定;
- 在事件处理器中直接赋值。
15.4 anchors 与 x、y 不要随意混用
例如,一个对象已经设置:
qml
anchors.horizontalCenter: parent.horizontalCenter
这时再设置:
qml
x: 100
可能无法得到预期结果,因为 anchors 正在负责对象的水平位置。
一般建议:
- 使用
anchors时,让anchors管理对应方向的位置; - 使用
x、y时,不要再对同一方向设置锚点。
15.5 Rectangle 与 Button 所属模块不同
Rectangle 通常来自:
qml
import QtQuick
Button 通常来自:
qml
import QtQuick.Controls
因此,只导入 QtQuick 时,不一定能直接使用 Button。
十六、本节知识总结
QML 的基础语法可以归纳为下面几个关键词:
| 关键词 | 作用 |
|---|---|
import |
导入 QML 模块 |
| Object | 表示界面对象 |
| Property | 描述对象状态 |
id |
唯一标识对象 |
x、y |
绝对定位 |
anchors |
相对定位 |
| Expression | 属性值计算 |
| Binding | 属性之间自动联动 |
onClicked |
处理点击事件 |
console.log() |
输出调试信息 |
QML 界面的基本组成可以概括为:
text
QML 界面 = 对象 + 属性 + 对象关系 + 事件处理
而 QML 最重要的特点之一是:
text
属性绑定
通过属性绑定,可以让界面中的对象自动响应数据变化,从而减少大量手动更新界面的代码。
十七、快速复习清单
复习时可以重点回答下面的问题:
- QML 是什么类型的语言?
import有什么作用?- 什么是 QML 对象?
- 属性和
id有什么区别? parent表示什么?x、y与anchors有什么区别?- 如何让对象在父对象中居中?
- 什么是属性绑定?
- 修改被依赖属性后,绑定属性会发生什么?
- 如何处理按钮点击事件?
- 如何在 Qt Creator 中输出调试信息?
- 直接给绑定属性赋值可能产生什么影响?
十八、一句话记忆
QML 通过对象描述界面,通过属性设置状态,通过 anchors 设置位置,通过属性绑定实现自动联动,通过信号处理器响应用户操作。