4. Qt Quick核心组件
Qt Quick 的界面由 QML 元素树构成,所有可视元素都直接或间接继承自 Item。掌握核心组件的属性与方法,是后续用 C++ 注册类型、暴露模型、双向通信的基础。本节围绕最常用的六类组件展开,先建立“Item 是根、其余是特化”的认知,再逐一拆解属性、方法与典型用法。
一、核心原理:Item 是所有可视元素的基类
Item 本身没有可见外观,但它定义了 Qt Quick 中一切可视元素共有的几何、层级、状态与事件能力。理解 Item,等于掌握了 QML 布局与交互的“公共语言”。
- 几何属性:
x、y、width、height、z,其中z决定同级元素的堆叠顺序。 - 锚定系统:
anchors提供fill、centerIn、left/right/top/bottom等关系,比绝对坐标更适应窗口缩放。 - 变换与裁剪:
scale、rotation、transformOrigin、clip控制视觉呈现。 - 状态与可见性:
visible、enabled、opacity、focus影响交互与渲染。 - 子元素管理:
children、resources、parent构成元素树,childAt()可按坐标查找子项。
关键点:Item 不绘制任何像素,但它的坐标系、锚定和层级规则会被 Rectangle、Text、Image 等子类完整继承。因此“先摆 Item,再放可视元素”是 QML 布局的常见思路。
二、常用组件属性与方法速查
下表汇总六类组件的核心能力,便于在编码时快速定位。
| 组件 | 核心属性 | 常用方法/信号 | 典型用途 |
|---|---|---|---|
| Item | x/y/width/height、anchors、z、visible、opacity | childAt()、contains()、mapToItem() | 容器、布局基准、坐标转换 |
| Rectangle | color、radius、border.width、border.color、gradient | 无特有方法,继承 Item | 背景、卡片、分割线、圆角按钮底 |
| Text | text、font、color、horizontalAlignment、wrapMode、elide | 无特有方法,继承 Item | 标题、标签、状态提示 |
| Image | source、fillMode、sourceSize、asynchronous、cache | 无特有方法,继承 Item | 图标、图片展示、异步加载 |
| MouseArea | anchors.fill、hoverEnabled、acceptedButtons、cursorShape | onClicked、onPressed、onReleased、onPositionChanged | 点击、拖拽、悬停交互 |
| Button | text、icon.source、checkable、checked、flat、highlighted | onClicked、onPressed、onToggled | 标准按钮、开关式按钮 |
三、方法流程:从静态界面到可交互组件
下面用一个“带图标的可点击卡片”示例,串联六类组件的协作方式。流程为:Item 定容器 → Rectangle 画背景 → Image 放图标 → Text 写标题 → MouseArea 接管点击 → Button 提供标准操作入口。
import QtQuick 2.15
import QtQuick.Controls 2.15
Item {
id: card
width: 320; height: 120
Rectangle {
id: bg
anchors.fill: parent
radius: 12
color: mouseArea.pressed ? "#d0e8ff" : "#f2f8ff"
border.width: 1
border.color: "#8ab4e8"
}
Image {
id: icon
source: "qrc:/icons/info.png"
width: 40; height: 40
anchors.left: parent.left
anchors.leftMargin: 16
anchors.verticalCenter: parent.verticalCenter
fillMode: Image.PreserveAspectFit
asynchronous: true
}
Text {
id: title
text: "设备状态"
font.pixelSize: 18
color: "#1f3a5f"
anchors.left: icon.right
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: console.log("卡片被点击")
}
Button {
text: "查看详情"
anchors.right: parent.right
anchors.rightMargin: 12
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
onClicked: console.log("按钮被点击")
}
}
该示例体现了几个关键协作点:anchors.fill 让 MouseArea 覆盖整张卡片;pressed 状态驱动背景色变化;Image.asynchronous 避免大图阻塞 UI;Text.elide 防止长文本溢出;Button 作为标准控件提供独立点击区域。
四、案例场景:状态面板的组件组合
假设要做一个设备状态面板,左侧显示图标,中间显示名称与数值,右侧提供“刷新”按钮。可以按以下结构组织:
- 用
Item作为根容器,设置固定宽高与锚定基准。 - 用
Rectangle绘制圆角背景,并通过border区分边界。 - 用
Image加载状态图标,fillMode选择PreserveAspectFit保持比例。 - 用两个
Text分别显示设备名和实时数值,数值可通过 C++ 属性绑定更新。 - 用
MouseArea实现整卡点击,用Button实现独立刷新操作。
当需要与 C++ 交互时,可把
Text.text 绑定到 C++ 对象的 Q_PROPERTY,把 MouseArea.onClicked 连接到 C++ 的 Q_INVOKABLE 方法,从而让 QML 负责展示、C++ 负责逻辑。五、误区与复盘
- 误区一:用绝对坐标代替锚定。 窗口缩放后布局错乱。应优先使用
anchors或Layout系列。 - 误区二:MouseArea 与 Button 事件冲突。 若 MouseArea 覆盖了 Button,按钮可能无法点击。应调整层级或缩小 MouseArea 范围。
- 误区三:Image 未设置 sourceSize 导致内存占用过高。 大图应配合
sourceSize与asynchronous使用。 - 误区四:Text 未设置 wrapMode 或 elide。 长文本会溢出容器,影响视觉与布局。
- 误区五:忽略 Item 的 z 值。 同级元素重叠时,后声明者默认在上层,必要时显式设置
z。
复盘建议:每写完一个组件组合,先检查锚定关系是否闭环、点击区域是否被遮挡、文本与图片是否自适应,再接入 C++ 数据。这样能把问题定位在 QML 层,避免与后端逻辑纠缠。