QML语法基础介绍

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 的主要特点包括:

  1. 语法简单,学习成本较低;
  2. 适合快速开发图形界面;
  3. 支持属性绑定;
  4. 支持动画和触摸交互;
  5. 可以与 JavaScript、C++ 配合使用;
  6. 适合桌面端、嵌入式设备和触摸屏应用。

二、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 是父对象;
  • ButtonRectangle 的子对象;
  • 按钮会显示在矩形内部。

四、属性与 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"
}

需要注意:

  1. 同一个 QML 作用域中的 id 不能重复;
  2. id 不需要加引号;
  3. id 通常使用小写字母开头;
  4. id 是 QML 的特殊标识,不是普通属性;
  5. 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 中常见的定位方式可以分为:

  1. 绝对定位;
  2. 相对定位;
  3. 布局管理器。

本节重点介绍前两种。


6.1 绝对定位

绝对定位通过 xy 设置对象的位置。

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
    }
}

每次点击按钮:

  1. 红色矩形宽度增加 10
  2. 蓝色矩形的宽度自动重新计算;
  3. 不需要手动修改蓝色矩形。

这就是属性绑定的优势:

一个属性发生变化后,依赖它的属性会自动更新。


十、固定值与属性绑定的区别

固定值:

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 导入模块;
  • 创建 WindowRectangleButton 对象;
  • 使用 id 标识对象;
  • 使用 widthheightcolor 等属性;
  • 使用 anchors 进行相对定位;
  • 使用 xy 进行绝对定位;
  • 使用表达式计算属性;
  • 使用属性绑定联动两个矩形;
  • 使用 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 管理对应方向的位置;
  • 使用 xy 时,不要再对同一方向设置锚点。

15.5 Rectangle 与 Button 所属模块不同

Rectangle 通常来自:

qml 复制代码
import QtQuick

Button 通常来自:

qml 复制代码
import QtQuick.Controls

因此,只导入 QtQuick 时,不一定能直接使用 Button


十六、本节知识总结

QML 的基础语法可以归纳为下面几个关键词:

关键词 作用
import 导入 QML 模块
Object 表示界面对象
Property 描述对象状态
id 唯一标识对象
xy 绝对定位
anchors 相对定位
Expression 属性值计算
Binding 属性之间自动联动
onClicked 处理点击事件
console.log() 输出调试信息

QML 界面的基本组成可以概括为:

text 复制代码
QML 界面 = 对象 + 属性 + 对象关系 + 事件处理

而 QML 最重要的特点之一是:

text 复制代码
属性绑定

通过属性绑定,可以让界面中的对象自动响应数据变化,从而减少大量手动更新界面的代码。


十七、快速复习清单

复习时可以重点回答下面的问题:

  • QML 是什么类型的语言?
  • import 有什么作用?
  • 什么是 QML 对象?
  • 属性和 id 有什么区别?
  • parent 表示什么?
  • xyanchors 有什么区别?
  • 如何让对象在父对象中居中?
  • 什么是属性绑定?
  • 修改被依赖属性后,绑定属性会发生什么?
  • 如何处理按钮点击事件?
  • 如何在 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 的主要特点包括:

  1. 语法简单,学习成本较低;
  2. 适合快速开发图形界面;
  3. 支持属性绑定;
  4. 支持动画和触摸交互;
  5. 可以与 JavaScript、C++ 配合使用;
  6. 适合桌面端、嵌入式设备和触摸屏应用。

二、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 是父对象;
  • ButtonRectangle 的子对象;
  • 按钮会显示在矩形内部。

四、属性与 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"
}

需要注意:

  1. 同一个 QML 作用域中的 id 不能重复;
  2. id 不需要加引号;
  3. id 通常使用小写字母开头;
  4. id 是 QML 的特殊标识,不是普通属性;
  5. 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 中常见的定位方式可以分为:

  1. 绝对定位;
  2. 相对定位;
  3. 布局管理器。

本节重点介绍前两种。


6.1 绝对定位

绝对定位通过 xy 设置对象的位置。

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
    }
}

每次点击按钮:

  1. 红色矩形宽度增加 10
  2. 蓝色矩形的宽度自动重新计算;
  3. 不需要手动修改蓝色矩形。

这就是属性绑定的优势:

一个属性发生变化后,依赖它的属性会自动更新。


十、固定值与属性绑定的区别

固定值:

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 导入模块;
  • 创建 WindowRectangleButton 对象;
  • 使用 id 标识对象;
  • 使用 widthheightcolor 等属性;
  • 使用 anchors 进行相对定位;
  • 使用 xy 进行绝对定位;
  • 使用表达式计算属性;
  • 使用属性绑定联动两个矩形;
  • 使用 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 管理对应方向的位置;
  • 使用 xy 时,不要再对同一方向设置锚点。

15.5 Rectangle 与 Button 所属模块不同

Rectangle 通常来自:

qml 复制代码
import QtQuick

Button 通常来自:

qml 复制代码
import QtQuick.Controls

因此,只导入 QtQuick 时,不一定能直接使用 Button


十六、本节知识总结

QML 的基础语法可以归纳为下面几个关键词:

关键词 作用
import 导入 QML 模块
Object 表示界面对象
Property 描述对象状态
id 唯一标识对象
xy 绝对定位
anchors 相对定位
Expression 属性值计算
Binding 属性之间自动联动
onClicked 处理点击事件
console.log() 输出调试信息

QML 界面的基本组成可以概括为:

text 复制代码
QML 界面 = 对象 + 属性 + 对象关系 + 事件处理

而 QML 最重要的特点之一是:

text 复制代码
属性绑定

通过属性绑定,可以让界面中的对象自动响应数据变化,从而减少大量手动更新界面的代码。


十七、快速复习清单

复习时可以重点回答下面的问题:

  • QML 是什么类型的语言?
  • import 有什么作用?
  • 什么是 QML 对象?
  • 属性和 id 有什么区别?
  • parent 表示什么?
  • xyanchors 有什么区别?
  • 如何让对象在父对象中居中?
  • 什么是属性绑定?
  • 修改被依赖属性后,绑定属性会发生什么?
  • 如何处理按钮点击事件?
  • 如何在 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 的主要特点包括:

  1. 语法简单,学习成本较低;
  2. 适合快速开发图形界面;
  3. 支持属性绑定;
  4. 支持动画和触摸交互;
  5. 可以与 JavaScript、C++ 配合使用;
  6. 适合桌面端、嵌入式设备和触摸屏应用。

二、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 是父对象;
  • ButtonRectangle 的子对象;
  • 按钮会显示在矩形内部。

四、属性与 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"
}

需要注意:

  1. 同一个 QML 作用域中的 id 不能重复;
  2. id 不需要加引号;
  3. id 通常使用小写字母开头;
  4. id 是 QML 的特殊标识,不是普通属性;
  5. 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 中常见的定位方式可以分为:

  1. 绝对定位;
  2. 相对定位;
  3. 布局管理器。

本节重点介绍前两种。


6.1 绝对定位

绝对定位通过 xy 设置对象的位置。

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
    }
}

每次点击按钮:

  1. 红色矩形宽度增加 10
  2. 蓝色矩形的宽度自动重新计算;
  3. 不需要手动修改蓝色矩形。

这就是属性绑定的优势:

一个属性发生变化后,依赖它的属性会自动更新。


十、固定值与属性绑定的区别

固定值:

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 导入模块;
  • 创建 WindowRectangleButton 对象;
  • 使用 id 标识对象;
  • 使用 widthheightcolor 等属性;
  • 使用 anchors 进行相对定位;
  • 使用 xy 进行绝对定位;
  • 使用表达式计算属性;
  • 使用属性绑定联动两个矩形;
  • 使用 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 管理对应方向的位置;
  • 使用 xy 时,不要再对同一方向设置锚点。

15.5 Rectangle 与 Button 所属模块不同

Rectangle 通常来自:

qml 复制代码
import QtQuick

Button 通常来自:

qml 复制代码
import QtQuick.Controls

因此,只导入 QtQuick 时,不一定能直接使用 Button


十六、本节知识总结

QML 的基础语法可以归纳为下面几个关键词:

关键词 作用
import 导入 QML 模块
Object 表示界面对象
Property 描述对象状态
id 唯一标识对象
xy 绝对定位
anchors 相对定位
Expression 属性值计算
Binding 属性之间自动联动
onClicked 处理点击事件
console.log() 输出调试信息

QML 界面的基本组成可以概括为:

text 复制代码
QML 界面 = 对象 + 属性 + 对象关系 + 事件处理

而 QML 最重要的特点之一是:

text 复制代码
属性绑定

通过属性绑定,可以让界面中的对象自动响应数据变化,从而减少大量手动更新界面的代码。


十七、快速复习清单

复习时可以重点回答下面的问题:

  • QML 是什么类型的语言?
  • import 有什么作用?
  • 什么是 QML 对象?
  • 属性和 id 有什么区别?
  • parent 表示什么?
  • xyanchors 有什么区别?
  • 如何让对象在父对象中居中?
  • 什么是属性绑定?
  • 修改被依赖属性后,绑定属性会发生什么?
  • 如何处理按钮点击事件?
  • 如何在 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 的主要特点包括:

  1. 语法简单,学习成本较低;
  2. 适合快速开发图形界面;
  3. 支持属性绑定;
  4. 支持动画和触摸交互;
  5. 可以与 JavaScript、C++ 配合使用;
  6. 适合桌面端、嵌入式设备和触摸屏应用。

二、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 是父对象;
  • ButtonRectangle 的子对象;
  • 按钮会显示在矩形内部。

四、属性与 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"
}

需要注意:

  1. 同一个 QML 作用域中的 id 不能重复;
  2. id 不需要加引号;
  3. id 通常使用小写字母开头;
  4. id 是 QML 的特殊标识,不是普通属性;
  5. 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 中常见的定位方式可以分为:

  1. 绝对定位;
  2. 相对定位;
  3. 布局管理器。

本节重点介绍前两种。


6.1 绝对定位

绝对定位通过 xy 设置对象的位置。

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
    }
}

每次点击按钮:

  1. 红色矩形宽度增加 10
  2. 蓝色矩形的宽度自动重新计算;
  3. 不需要手动修改蓝色矩形。

这就是属性绑定的优势:

一个属性发生变化后,依赖它的属性会自动更新。


十、固定值与属性绑定的区别

固定值:

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 导入模块;
  • 创建 WindowRectangleButton 对象;
  • 使用 id 标识对象;
  • 使用 widthheightcolor 等属性;
  • 使用 anchors 进行相对定位;
  • 使用 xy 进行绝对定位;
  • 使用表达式计算属性;
  • 使用属性绑定联动两个矩形;
  • 使用 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 管理对应方向的位置;
  • 使用 xy 时,不要再对同一方向设置锚点。

15.5 Rectangle 与 Button 所属模块不同

Rectangle 通常来自:

qml 复制代码
import QtQuick

Button 通常来自:

qml 复制代码
import QtQuick.Controls

因此,只导入 QtQuick 时,不一定能直接使用 Button


十六、本节知识总结

QML 的基础语法可以归纳为下面几个关键词:

关键词 作用
import 导入 QML 模块
Object 表示界面对象
Property 描述对象状态
id 唯一标识对象
xy 绝对定位
anchors 相对定位
Expression 属性值计算
Binding 属性之间自动联动
onClicked 处理点击事件
console.log() 输出调试信息

QML 界面的基本组成可以概括为:

text 复制代码
QML 界面 = 对象 + 属性 + 对象关系 + 事件处理

而 QML 最重要的特点之一是:

text 复制代码
属性绑定

通过属性绑定,可以让界面中的对象自动响应数据变化,从而减少大量手动更新界面的代码。


十七、快速复习清单

复习时可以重点回答下面的问题:

  • QML 是什么类型的语言?
  • import 有什么作用?
  • 什么是 QML 对象?
  • 属性和 id 有什么区别?
  • parent 表示什么?
  • xyanchors 有什么区别?
  • 如何让对象在父对象中居中?
  • 什么是属性绑定?
  • 修改被依赖属性后,绑定属性会发生什么?
  • 如何处理按钮点击事件?
  • 如何在 Qt Creator 中输出调试信息?
  • 直接给绑定属性赋值可能产生什么影响?

十八、一句话记忆

QML 通过对象描述界面,通过属性设置状态,通过 anchors 设置位置,通过属性绑定实现自动联动,通过信号处理器响应用户操作。