2. Qt Quick基础
Qt Quick 是 Qt 面向现代 UI 的声明式框架,QML 是它的描述语言。与传统的 QWidget 命令式构建界面不同,QML 用“对象树 + 属性”的方式描述界面:你声明有哪些元素、它们长什么样、彼此如何关联,运行时由 Qt Quick 引擎负责渲染与更新。理解 QML 语法、基础可视元素以及属性绑定机制,是后续多屏交互工程的地基。
一、QML 语法:对象、属性与层级
QML 文件本质上是一棵对象树。每个元素是一个对象,对象用大括号声明属性,属性用 属性名: 值 的形式赋值。元素之间的父子关系既决定渲染层级,也决定坐标系的相对关系。
import QtQuick 2.15
Rectangle {
id: root
width: 320; height: 200
color: "#eaf4ff"
Text {
id: title
anchors.centerIn: parent
text: "多屏交互面板"
font.pixelSize: 20
color: "#1b4f8a"
}
}
要点有三:id 是对象在文件内的唯一引用名,用于跨元素访问;属性赋值既可以是常量,也可以是表达式;父子关系通过嵌套或 parent 属性建立。子元素的坐标默认相对父元素,因此移动父元素会带动整棵子树。
二、基础可视元素:Item、Rectangle、Text、Image
Item 是所有可视元素的基类,本身不绘制任何内容,但提供位置、尺寸、锚点、变换、透明度、层级等通用能力。它常被用作容器或逻辑分组节点。
Rectangle 在 Item 基础上增加了填充色、边框、圆角,是最常用的背景与卡片元素。Text 负责文本显示,支持字号、颜色、换行、省略与对齐。Image 负责位图显示,通过 source 指定资源,fillMode 控制缩放策略,asynchronous 可避免大图阻塞界面。
| 元素 | 核心用途 | 常用属性 |
|---|---|---|
| Item | 容器、分组、逻辑节点 | x、y、width、height、anchors、visible、opacity、z |
| Rectangle | 背景、卡片、分隔、色块 | color、border.color、border.width、radius |
| Text | 标题、标签、状态文本 | text、font.pixelSize、color、wrapMode、elide |
| Image | 图标、图片、缩略图 | source、fillMode、sourceSize、asynchronous |
三、属性绑定机制:QML 的灵魂
属性绑定是 QML 区别于普通 UI 框架的关键。当属性值写成表达式时,QML 会记录该表达式依赖了哪些属性;一旦依赖项变化,表达式自动重新求值并更新目标属性。这种“依赖追踪 + 自动重算”让界面状态与数据保持同步,无需手写刷新逻辑。
Rectangle {
id: card
width: 240; height: 120
color: "#ffffff"
Rectangle {
id: bar
width: card.width * 0.6 // 绑定:随 card.width 变化
height: 8
color: "#2f9e6e"
anchors.bottom: parent.bottom
}
Text {
text: "宽度:" + bar.width // 绑定:随 bar.width 变化
}
}
绑定可以是简单引用,也可以是函数调用、条件表达式或字符串拼接。需要注意:一旦对已绑定的属性再次用命令式赋值,绑定会被破坏。例如先写 width: parent.width / 2,之后又执行 bar.width = 100,绑定即失效,后续父宽度变化不再影响它。若确实需要动态切换,应使用 Qt.binding() 重新建立绑定。
console.log(),观察依赖属性变化时表达式是否被重新求值,从而判断绑定是否仍然有效。四、锚点布局与多屏场景的关联
锚点(anchors)是 QML 中最常用的相对布局方式,通过 anchors.fill、anchors.centerIn、anchors.left/right/top/bottom 等把元素与父元素或兄弟元素对齐。锚点本身也是绑定:父元素尺寸变化时,被锚定的元素会自动跟随。
在多屏交互工程中,这一特性尤为重要。不同屏幕的分辨率、DPI、宽高比可能不同,若用固定像素写死布局,跨屏时极易错位。更稳妥的做法是:外层用 Item 或 Rectangle 作为屏幕根容器,内部元素通过锚点和比例绑定自适应,再结合 Screen 提供的屏幕信息做差异化处理。
五、案例:多屏状态卡片
假设要做一个显示“屏幕连接状态”的卡片,卡片宽度随窗口变化,状态色随连接状态变化,文本随状态更新。用绑定可以一次写完,无需手动刷新:
Rectangle {
id: statusCard
width: parent.width * 0.9
height: 90
radius: 10
color: connected ? "#e8f7ee" : "#fdecec"
border.color: connected ? "#2f9e6e" : "#d9534f"
border.width: 2
property bool connected: true
Text {
anchors.centerIn: parent
text: connected ? "屏幕已连接" : "屏幕未连接"
color: connected ? "#1f7a4d" : "#a33"
font.pixelSize: 18
}
}
这里 connected 是自定义属性,改变它即可同时驱动背景色、边框色和文本内容,这正是绑定的价值:一处状态变化,多处视图同步。
六、常见误区与复盘
- 用命令式赋值覆盖绑定:在 JavaScript 函数里写
rect.width = 200,会切断原有绑定,后续父宽度变化不再生效。 - 在绑定中做重计算:绑定表达式应尽量轻量,避免在表达式中执行复杂循环或频繁 I/O,否则每次依赖变化都会带来性能开销。
- 锚点与绝对坐标混用:同一元素既设
anchors.fill又设x/y,容易产生冲突或警告,应统一布局策略。 - 忽略 Image 的加载状态:大图未设置
asynchronous或sourceSize时,可能造成首屏卡顿,多屏场景下更明显。
掌握 QML 语法、四类基础元素与属性绑定机制后,你就具备了用声明式方式描述多屏界面的能力。后续的布局、状态机、动画与多屏协同,都建立在这套“对象树 + 绑定”的模型之上。