A component is a reusable element. QML provides different ways to create components. Currently, we will look only at the simplest form - a file-based component. A file-based component is created by placing a QML element in a file and giving the file an element name (e.g. Button.qml
). You can use the component like every other element from the Qt Quick module. In our case, you would use this in your code as Button { ... }
.
组件是可重用的元素类型。QML提供了不同的创建组件的方法。现在,看下最简单的方法—基于文件的组件。基于文件的组件是通过在文件中放置一个QML元素类型,并为该文件指定一个元素名(例如Button.qml)来创建。可以像使用Qt Quick模块中的其他元素类型一样使用该组件。在我们的例子中,可以在代码中使用这个组件Button {…}。
For example, let’s create a rectangle containing a text component and a mouse area. This resembles a simple button and doesn’t need to be more complicated for our purposes.
例如,我们创建一个包含文本组件和鼠标区域的矩形。这就像一个简单的按钮,但我们不需要复杂功能。
Rectangle { // our inlined button ui 自己实现的按钮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 { // text changes when button was clicked 按钮单击时,文字也发生变化
id: status
x: 12; y: 76
width: 116; height: 26
text: "waiting ..."
horizontalAlignment: Text.AlignHCenter
}
The UI will look similar to this. In the first image, the UI is in its initial state, and in the second image the button has been clicked.
UI运行后显示如下。在第一张图片中,UI处于初始状态,而在第二张图片中按钮已经被单击。
Now our task is to extract the button UI into a reusable component. For this, we should think about a possible API for our button. You can do this by imagining how someone else should use your button. Here’s what I came up with:
现在我们的任务是将按钮UI提取到一个可重用组件中。为此,应该考虑为按钮增加一个事件处理的API。可以通过想象别人应该如何使用按钮来做到这一点。这是我的想法
// minimal API for a button 一个按钮的最小API实现
Button {
text: "Click Me"
onClicked: { /* do something */ }
}
I would like to set the text using a text
property and to implement my own click handler. Also, I would expect the button to have a sensible initial size, which I can overwrite (e.g. with width: 240
for example).
使用文本属性(text)设置文本,并实现点击事件处理器。此外,希望按钮有一个合理的初始大小,也可以修改它的大小(例如宽度:240)。
To achieve this we create a Button.qml
file and copy our button UI inside. Additionally, we need to export the properties a user might want to change at the root level.
完成后,就创建了一个Button. qml的文件,和复制按钮UI代码到文件里。然后,需要导出用户可能会在根级别更改的属性。
// Button.qml
import QtQuick
Rectangle {
id: root
// export button properties 导出按钮属性
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()
}
}
}
We have exported the text property and the clicked signal at the root level. Typically we name our root element root to make referencing it easier. We use the alias
feature of QML, which is a way to export properties inside nested QML elements to the root level and make this available for the outside world. It is important to know that only the root level properties can be accessed from outside this file by other components.
我们已经在根级别导出了文本属性和单击信号。通常,我们将根元素命名为root,以便引用它。我们使用QML的别名(alias)特性,将嵌套QML元素中的属性,导出到根级别的属性,以便外部可以使用它。需要知道的是,只有根级别的属性,可以被其他组件从文件外部访问。
To use our new Button
element we can simply declare it in our file. So the earlier example will become a little bit simplified.
要使用新的Button元素类型,我们只需在文件中声明它。前面的示例会变得简化一点。
Button { // our Button component 我们的按钮组件
id: button
x: 12; y: 12
text: "Start"
onClicked: {
status.text = "Button clicked!"
}
}
Text { // text changes when button was clicked 按钮单击时,文字也发生变化
id: status
x: 12; y: 76
width: 116; height: 26
text: "waiting ..."
horizontalAlignment: Text.AlignHCenter
}
Now you can use as many buttons as you like in your UI by just using Button { ... }
. A real button could be more complex, e.g providing feedback when clicked or showing a nicer decoration.
现在可以在UI中任意使用按钮了,只要使用Button{…}。当然一个真正的按钮可能会更复杂,例如在点击时,提供反馈或显示更看。
TIP
注
If you want to, you could even go a step further and use an Item
as a root element. This prevents users from changing the color of the button we designed, and provides us with more control over the exported API. The target should be to export a minimal API. Practically, this means we would need to replace the root Rectangle
with an Item
and make the rectangle a nested element in the root item.
如果您愿意,甚至可以更进一步,使用Item作为根元素。这可以防止用户改变我们设计的按钮颜色,并为提供对导出API的更多控制。这次的目的是导出最小的API。实际上,这需要将根矩形替换为Item,并使矩形成为根项中的嵌套元素。
Item {
id: root
width: 116; height: 26
property alias text: label.text
signal clicked
Rectangle {
anchors.fill parent
color: "lightsteelblue"
border.color: "slategrey"
}
...
}
With this technique, it is easy to create a whole series of reusable components.
使用这种技术,很容易创建一套可重用组件。
示例源码下载