# 组件
组件是可复用的元素。QML 提供了创建组件的多种方式。目前,我们仅专注于最简单的形式——基于文件的组件。创建基于文件的组件是通过将 QML 元素放入一个文件,且将文件名命名为元素(如 Button.qml
)。你可像使用来自 Qt Quick 模块的其它元素一样的使用此组件。在我们的实例中,你的代码应用像这样 Button { ... }
。
举例来说,我们先创建一个矩形区域,其包含了一个文本组件和鼠标区域。这看起来像个按钮,对于我们来说,这就够了。
Rectangle { // 我们的行内按钮 ui
id: button
x: 12; y: 12
width: 116; height: 26
color: "lightsteelblue"
border.color: "slategrey"
Text {
anchors.centerIn: parent
text: "Start"
}
MouseArea {
anchors.fill: parent
onClicked: {
status.text = "Button clicked!"
}
}
}
Text { // 当点击按钮时修改文本
id: status
x: 12; y: 76
width: 116; height: 26
text: "waiting ..."
horizontalAlignment: Text.AlignHCenter
}
UI 看起来如下。在第一张图中,UI 是其初始状态,第二张图中,按钮被点击了。
现在我们的任务将按钮 UI 提取成可复用的组件。为此,我们需先考虑按钮可能的 API。想象别人应该如何使用该按钮。这是我能想到的:
// 一个按钮的最小 API
Button {
text: "Click Me"
onClicked: { /* 做点啥 */ }
}
可以通过 text
属性修改文本,且实现自定义点击处理器。当然,也可以给按钮一个预设的合理大小,便于后续覆盖(本例中使用了 width: 240
)。
为此,我们创建了一个 Button.qml
文件,且将按钮代码复制到里面。此外,我们需要在根级别导出用户可能要修改的属性。
// Button.qml
import QtQuick
Rectangle {
id: root
// 导出按钮属性
property alias text: label.text
signal clicked
width: 116; height: 26
color: "lightsteelblue"
border.color: "slategrey"
Text {
id: label
anchors.centerIn: parent
text: "Start"
}
MouseArea {
anchors.fill: parent
onClicked: {
root.clicked()
}
}
}
我们已在根级别导出文本属性和点击信号。一般来说,我们将根元素命名为 root,便于后续引用。我们使用了 QML 提供的 alias
特性,这是一种在 QML 元素内部根级别导出属性的方法,这使得这些属性对外部可用。必须明确,只有根级别的属性可被文件外的其它组件访问到。
要使用我们的新 Button
元素,可用简单地在文件内声明它。所以,前面的例子可用再度简化。
Button { // 我们的按钮组件
id: button
x: 12; y: 12
text: "Start"
onClicked: {
status.text = "Button clicked!"
}
}
Text { // 当点击按钮时,文本会修改
id: status
x: 12; y: 76
width: 116; height: 26
text: "waiting ..."
horizontalAlignment: Text.AlignHCenter
}
现在,你可用通过 Button { ... }
在 UI 中使用任意的按钮。一个实际的按钮会更加复杂,例如,提供点击反馈或展示装饰。
提示
如果你想的话,可以更进一步,将 Item
作为根元素。这会阻止用户修改我们设计的按钮的颜色,且让我们更好的控制导出 API。目标是导出最少的 API。实际上,这意味着我们要将根元素 Rectangle
替换为 Item
,并将原来的矩形元素嵌入新的根元素。
Item {
id: root
width: 116; height: 26
property alias text: label.text
signal clicked
Rectangle {
anchors.fill parent
color: "lightsteelblue"
border.color: "slategrey"
}
...
}
通过此技术,创建整套的可复用组件变得很简单。