文章目录
一、QML 的基本组成
QML是一种描述用户界面的声明式语言。它将用户界面分解成一些更小的元素,这些元素能够结合成一个组件。QML语言描述了用户界面元素的形状和行为。用户界面能够使用JavaScript来提供修饰,或者增加更加复杂的逻辑。从这个角度来看它遵循HTML-JavaScript模式,但QML是被设计用来描述用户界面的,而不是文本文档。从QML元素的层次结构来理解是最简单的学习方式。子元素从父元素上继承了坐标系统,它的x,y坐标总是相对应于它的父元素坐标系统。
QML 文件以 .qml 结尾,通常由以下部分组成:
import QtQuick 2.12
// 根元素是矩形
Rectangle {
// 将此元素命名为 root
id: root
// 属性: <name>: <value>
width: 120; height: 240
// color 属性
color: "#D8D8D8"
// 声明嵌套元素(根元素的子元素)
Image {
id: rocket
// 引用父级
x: (parent.width - width)/2; y: 40
source: 'assets/rocket.png'
}
// root 的另一个元素
Text {
// 未命名元素
// 通过 id 引用元素
y: rocket.y + rocket.height + 20
// 引用根元素
width: root.width
horizontalAlignment: Text.AlignHCenter
text: 'Rocket'
}
}
- import声明导入了一个指定的模块版本。一般来说会导入QtQuick2.0来作为初始元素的引用。
- 使用//可以单行注释,使用/**/可以多行注释,就像C/C++和JavaScript一样。
- 每一个QML文件都需要一个根元素,就像HTML一样。
- 一个元素使用它的类型声明,然后使用{}进行包含。
- 元素拥有属性,他们按照name:value的格式来赋值。
- 任何在QML文档中的元素都可以使用它们的id进行访问(id是一个任意的标识符)。
- 元素可以嵌套,这意味着一个父元素可以拥有多个子元素。子元素可以通过访问parent关键字来访问它们的父元素。
注意事项:
如果会经常使用id或者关键字parent来访问你的父对象。有一个比较好的方法是命名你的根元素对象id为root(id:root),这样就不用去思考你的QML文档中的根元素应该用什么方式命名了。
二、QML 的核心语法和特性
2.1 类型声明
QML 是基于对象的,每个组件都有类型。例如:
- Rectangle、Text、Image、MouseArea 是基本 UI 类型
- 也可以自定义类型(用另一个 .qml 文件)
2.2 属性赋值
属性值支持直接赋值、绑定表达式、函数:
width: 100 // 常量赋值
height: width / 2 // 属性绑定表达式
color: mouseArea.pressed ? "red" : "blue" // 动态绑定
2.3 信号与处理函数
QML 支持声明信号和处理器,响应事件非常简单:
MouseArea {
anchors.fill: parent
onClicked: {
console.log("Clicked!")
}
}
2.4 动画支持
内建支持动画,如 NumberAnimation、PropertyAnimation 等:
Rectangle {
id: rect
width: 100; height: 100; color: "red"
MouseArea {
anchors.fill: parent
onClicked: rect.color = "green"
}
Behavior on color {
ColorAnimation { duration: 500 }
}
}
2.5 条件与循环
可通过 visible, enabled, ListModel, Repeater 等实现逻辑:
Repeater {
model: 5
Rectangle {
width: 50; height: 50
color: "blue"
}
}
三、QML 模块和常用类型
QtQuick 常用类型:
- Item:所有可视元素的基类
- Rectangle:可绘制矩形,常用于布局和背景
- Text:文本显示
- Image:图像显示
- MouseArea:鼠标响应区域
- ListView:滚动列表视图
- Repeater:重复组件的生成器
- Timer:定时器
- State, Transition:状态切换与动画支持
四、与 JavaScript 和 C++ 交互
JavaScript:
可以直接在 QML 中嵌入 JavaScript 逻辑:
function double(x) {
return x * 2;
}
与 C++ 交互:
通过 QQmlContext 注册对象或 qmlRegisterType 注册类型。
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("myObject", &myObject);
Text {
text: myObject.getMessage()
}
五、QML 与 QQuickWindow/QQuickView 启动流程
完整示例:
import QtQuick 2.12
import QtQuick.Controls 2.12
ApplicationWindow {
visible: true
width: 400
height: 300
title: "Login Example"
Column {
spacing: 10
anchors.centerIn: parent
TextField {
id: username
placeholderText: "Username"
}
TextField {
id: password
placeholderText: "Password"
echoMode: TextInput.Password
}
Button {
text: "Login"
onClicked: {
console.log("Logging in as " + username.text)
}
}
}
}
C++ 端加载 QML:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
输出结果: