列数可变的 QML 中继器和 QML 网格布局
Posted
技术标签:
【中文标题】列数可变的 QML 中继器和 QML 网格布局【英文标题】:QML Repeater and QML Grid Layout with variable number of columns 【发布时间】:2017-12-04 17:10:43 【问题描述】:我有一个由具有某些属性的对象组成的模型,例如:
ListModel
id: fruitModel
ListElement
name: "Apple"
color: "green"
cost: 2.45
ListElement
name: "Orange"
color: "orange"
cost: 3.25
ListElement
name: "Banana"
color: "yellow"
cost: 1.95
现在我想使用GridLayout
显示这个模型。对于每个属性,我想在GridLayout
中使用一个元素,例如:
GridLayout
columns: 3
Text text: "Apple"
Rectangle color: "green"
SpinBox value: 2.45
Text text: "Orange"
Rectangle color: "orange"
SpinBox value: 3.25
Text text: "Banana"
Rectangle color: "yellow"
SpinBox value: 1.95
关键是我可以轻松更改GridLayout
的columns
属性并使我的布局更窄(例如,以适应小屏幕)。我可以使用Repeater 来填充GridLayout
。但是这种方法会以错误的顺序填充我的GridLayout
:
GridLayout
columns: 3
Repeater
model: fruitModel
Text text: name
Repeater
model: fruitModel
Rectangle color: color
Repeater
model: fruitModel
SpinBox value: value
使用Layout.column
和Layout.row
附加属性是浪费,因为我想轻松更改GridLayout
中的列数。
有什么方法可以用模型中的数据逐行填充GridLayout
?
UPD1:
我想要得到的行为:
GridLayout
columns: parent.width > 235 ? 3 : 1
Text text: "Apple"
Rectangle color: "green"; width: 40; height: 40
SpinBox value: 2
Text text: "Orange"
Rectangle color: "orange"; width: 40; height: 40
SpinBox value: 3
Text text: "Banana"
Rectangle color: "yellow"; width: 40; height: 40
SpinBox value: 1
UPD2: 来自@m7913d 的修改变体:
GridLayout
id: layout
property int maxColumns: 3
columns: parent.width > 235 ? maxColumns : 1
Repeater
model: fruitModel
Text
text: name
Layout.row: layout.columns == maxColumns ? index : (maxColumns * index)
Layout.column: 0
Repeater
model: fruitModel
Rectangle
Layout.preferredWidth: 30
Layout.preferredHeight: 30
color: col
Layout.row: layout.columns == maxColumns ? index : (maxColumns * index + 1)
Layout.column: layout.columns == maxColumns ? 1 : 0
Repeater
model: fruitModel
SpinBox
value: val
Layout.row: layout.columns == maxColumns ? index : (maxColumns * index + 2)
Layout.column: layout.columns == maxColumns ? 2 : 0
它正在工作,但不容易修改解决方案,而且有时在布局调整大小期间会有消息QGridLayoutEngine::addItem: Cell (1, 0) already taken
。
【问题讨论】:
Populate GridLayout with Repeater的可能重复 不幸的是“使用Repeater填充GridLayout”中的解决方案使用Layout.column
和Layout.row
附加属性,因此无法动态更改GridLayout的columns
属性。
您可以展示您想要获得的图表或图像
@KamilZaripov,你调查过Flow
吗?这可能会为您提供所需的响应式布局。
是的,也许会有所帮助,但是如何使用模型中的项目填充Flow
?
【参考方案1】:
我会使用由Row
s 或Column
s(或任何其他安排)填充的Column
作为代表。
Column
id: rootCol
anchors.fill: parent
Repeater
model: fruitModel
delegate: rootCol.width > 300 ? rowDel : colDel
Component
id: rowDel
Row
Text width: 100; height: 50; text: model.name
Rectangle width: 50; height: 50; color: model.color
SpinBox width: 150; height: 50; value: model.cost
Component
id: colDel
Column
Text width: 100; height: 50; text: model.name
Rectangle width: 50; height: 50; color: model.color
SpinBox width: 150; height: 50; value: model.cost
或许:
Column
id: rootCol
anchors.fill: parent
Repeater
model: fruitModel
delegate: Flow
anchors
left: parent.left
right: parent.right
Text width: 100; height: 50; text: model.name
Rectangle width: 50; height: 50; color: model.color
SpinBox width: 150; height: 50; value: model.value
【讨论】:
是的,它有效,但在这种情况下,它不是GridLayout
,而是RowLayout
在ColumnLayout
内。它们是有区别的。在GridLayout
中,同一列中的所有项目都具有相同的宽度,但在RowLayout
中ColumnLayout
内部却没有。
通过一些工作,您可以自己实现该行为。 GridLayout
不会变魔术。
是的,我知道没有GridLayout
也可以做到这一点,而且目前我在ColumnLayout
内部使用RowLayout
,并且我手动为Item
s 设置了相同的宽度同一列。但这不是很方便的方法,我只是想知道是否有更简单的方法。显然没有。【参考方案2】:
这是另一个解决方案:
理念:按正确的顺序添加孩子
为此,我们需要确保所有Item
s 都是模型条目。
GridLayout
id: gl
columns: parent.width > 235 ? 3 : 1
Instantiator
model: fruitModel
delegate: QtObject
property Item text: Text parent: gl; text: model.name
property Item rect: Rectangle parent: gl; color: model.color; width: 50; height: 50;
property Item spin: SpinBox parent: gl; value: model.cost;
注意:当模型中的条目将被插入或重新排序时,这将失败,因为在此解决方案中,条目始终是附加的。 除此之外,它会自动支持列更改
【讨论】:
【参考方案3】:一种可能的方法是使用条件列/行索引扩展this method:
GridLayout
id:gridLayout
columns: parent.width > 235 ? 3 : 1
Repeater
model: fruitModel
implicitHeight: 50
Text
text: name
Layout.row: gridLayout.columns == 3 ? index : 3 * index
Layout.column: 0
Repeater
model: fruitModel
Rectangle
color: model.color
implicitWidth: 50
implicitHeight: 50
Layout.row: gridLayout.columns == 3 ? index : 3 * index + 1
Layout.column: gridLayout.columns == 3 ? 1 : 0
Repeater
model: fruitModel
SpinBox
value: value
Layout.row: gridLayout.columns == 3 ? index : 3 * index + 2
Layout.column: gridLayout.columns == 3 ? 2 : 0
【讨论】:
我已经尝试过这种方法,经过一些修改它可以工作,但它看起来有点难看,有时它会写入输出QGridLayoutEngine::addItem: Cell (1, 0) already taken
等等。
@KamilZaripov:请编辑此答案,或自己发布答案。问题部分没有答案。以上是关于列数可变的 QML 中继器和 QML 网格布局的主要内容,如果未能解决你的问题,请参考以下文章