4.8 用于定位的元素
有许多用于定位 Item 的 QML 元素。这些被称为定位器,并且在 QtQuick 模块中提供了以下内容:Row、Column、Grid 和 Flow。我们会在接下来介绍它们的显示内容的效果。
** 注意: **
在讨论细节之前,让我介绍一些辅助元素。红色,蓝色,绿色,浅色和深色的方块。每个组件都包含一个 48 x 48 像素的彩色矩形。这里是 RedSquare 的源代码:
// RedSquare.qml
import QtQuick 2.5
Rectangle {
width: 48
height: 48
color: "#ea7025"
border.color: Qt.lighter(color)
}
请注意使用 Qt.lighter(color) 来产生较浅的边框颜色。在下一个示例中,我们将使用这些帮助器,使源代码更加紧凑和易读。请记住,每个矩形的初始值为 48 x 48 像素。
Column (列)元素将子项安排到列中,将它们堆叠在一起。spacing (间距)属性可用于分隔每个子元素之间的距离。

// column.qml
import QtQuick 2.5
DarkSquare {
id: root
width: 120
height: 240
Column {
id: row
anchors.centerIn: parent
spacing: 8
RedSquare { }
GreenSquare { width: 96 }
BlueSquare { }
}
}
Row 元素将它的子项放在一起,从左到右,或者从右到左排列,这取决于 layoutDirection 属性。同样,spacing 属性是用来分隔子项的。

// row.qml
import QtQuick 2.5
BrightSquare {
id: root
width: 400; height: 120
Row {
id: row
anchors.centerIn: parent
spacing: 20
BlueSquare { }
GreenSquare { }
RedSquare { }
}
}
Grid 元素在网格中安排其子元素,通过设置 rows 和 columns 属性,可以限制行或列的数量。如果仅设置它们中的任何一个,另一个是根据子条目的数量来计算的。例如,将行设置为 3 并添加 6 个子项将会导致 2 列。属性 flow 和 layoutDirection 用于控制将条目添加到网格的顺序,而 spacing 控制子项的分隔空间。

// grid.qml
import QtQuick 2.5
BrightSquare {
id: root
width: 160
height: 160
Grid {
id: grid
rows: 2
columns: 2
anchors.centerIn: parent
spacing: 8
RedSquare { }
RedSquare { }
RedSquare { }
RedSquare { }
}
}
最后的定位器是 flow。它在流中添加子项。流的方向是使用 flow 和 layoutDirection 来控制的。它可以从侧面或者从顶部到底部。它也可以从左向右或相反方向运行。当这些项被添加到流中时,它们会被包装成新的行或列。为了让一个流工作,它必须有一个宽度或一个高度。可以直接设置,也可以通过设置锚布局来实现。

// flow.qml
import QtQuick 2.5
BrightSquare {
id: root
width: 160
height: 160
Flow {
anchors.fill: parent
anchors.margins: 20
spacing: 20
RedSquare { }
BlueSquare { }
GreenSquare { }
}
}
经常在定位器使用的一个元素是 Repeater。它的工作原理类似于 for 循环,并在模型上迭代。在最简单的情况下,模型只是提供循环数量的一个值。

// repeater.qml
import QtQuick 2.5
DarkSquare {
id: root
width: 252
height: 252
property variant colorArray: ["#00bde3", "#67c111", "#ea7025"]
Grid{
anchors.fill: parent
anchors.margins: 8
spacing: 4
Repeater {
model: 16
Rectangle {
width: 56; height: 56
property int colorIndex: Math.floor(Math.random()*3)
color: root.colorArray[colorIndex]
border.color: Qt.lighter(color)
Text {
anchors.centerIn: parent
color: "#f0f0f0"
text: "Cell " + index
}
}
}
}
}
在这个 Repeater 示例中,我们使用了一些新的魔法。我们定义自己的颜色属性,我们用它作为一组颜色。Repeater 创建了一系列的矩形(由模型定义的 16 个矩形)。对于每个循环,他创建一个矩形,由 Repeater 的子定义。在矩形中,我们使用 JS 数学函数 Math.floor(Math.random()*3) 来随机选择颜色。这给了我们一个从 0 到 2 的随机数字。我们用来从颜色数组中选择颜色。正如前面提到的,JavaScript 是 Qt Quick 的核心部分,因此我们可以自由地使用这些标准库。
Repeater 将 index 属性注入到 Repeater 中。它包含当前的循环索引。(0、1、...、15)。我们可以使用这个来根据 index 来做出自己的决定,或者在我们的例子中使用文本元素来可视化当前的 index。
** 注意: **
更高级的模型和动态视图的动态视图的更高级的处理被包含在模型视图(model-view)的章节中。当提供少量静态数据时,最好使用 Repeater 。
4.9 对元素进行布局
QML 提供了一种灵活的方式用来锚定元素。锚定的概念是元素基本属性的一部分,可用于所有可视的 QML 元素。锚的作用类似于合同,比几何变化更强。锚是一种相对的布局方法,我们总是需要一个相关的元素来进行锚定。

每个元素有 6 个主锚线(top、bottom、left、right、horizontalCenter、verticalCenter)。另外还有文本元素中文本的基线锚。每个锚点都有一个偏移量。在 top、bottom、left 和 right ,它们被称为边距。对于水平中心,垂直中心和基线,它们被称为偏移量。

- 元素填充了父元素:
GreenSquare {
BlueSquare {
width: 12
anchors.fill: parent
anchors.margins: 8
text: '(1)'
}
}
- 元素与父元素左侧保持一致:
GreenSquare {
BlueSquare {
width: 48
y: 8
anchors.left: parent.left
anchors.leftMargin: 8
text: '(2)'
}
}
- 元素的左侧与父元素右侧对齐:
GreenSquare {
BlueSquare {
width: 48
anchors.left: parent.right
text: '(3)'
}
}
- 中心对齐元素。Blue1 的是水平居中的父结点。Blue2 也是水平居中,但是显示在 Blue1 的上面,这是因为它的顶部与 Blue1 的底部对齐:
GreenSquare {
BlueSquare {
id: blue1
width: 48; height: 24
y: 8
anchors.horizontalCenter: parent.horizontalCenter
}
BlueSquare {
id: blue2
width: 72; height: 24
anchors.top: blue1.bottom
anchors.topMargin: 4
anchors.horizontalCenter: blue1.horizontalCenter
text: '(4)'
}
}
- 元素以父元素为中心:
GreenSquare {
BlueSquare {
width: 48
anchors.centerIn: parent
text: '(5)'
}
}
- 元素的中心是使用相对于父元素的水平和垂直中心,并且相对父元素向左偏移 12 像素:
GreenSquare {
BlueSquare {
width: 48
anchors.horizontalCenter: parent.horizontalCenter
anchors.horizontalCenterOffset: -12
anchors.verticalCenter: parent.verticalCenter
text: '(6)'
}
}
** 注意: **
在实际的代码中我们的方块已经被增强,以支持拖动。试试拖动一些方块。我们将发现 (1) 不能被拖动,因为它被锚定在父对象的所有的边上,当然我们也可以拖动 (1) 的父对象,因为它根本没有进行锚定。(2) 可以垂直拖动,因为它的左边是锚定的。类似的情况也适用于 (3)。(4) 只能垂直拖动,因为两个正方形都是水平居中。(5) 以父元素为中心,因此不能被拖动,类似于 (7)。拖动一个元素就意味着改变它们的 x、y 位置。由于锚固定比 x、y 的几何变化更强,所以拖拽被锚定线所限制。当后面我们讨论动画时,我们也将会看到这个效果。
本文参考链接:Quick Starter
网友评论