如何重新排序 QML GridLayout 中的项目?
How can I reorder the items in a QML GridLayout?
如何重新排序 GridLayout(或其他 QML 项目容器)中的项目?我有一个有一定数量的行和列,并填充了子项。直到几分钟前,我还希望我可以简单地操作项目的 children
列表成员来重新排序它们:我在 UI 中有一个 MouseArea
按钮,我希望从中可以只需调用(来自 onClicked:
)a
function reorder() {children.unshift(children.pop());}
布局项的方法(意图是布局中的最后一项成为第一项),但触发时会生成错误消息:
TypeError: Property 'pop' of object [object Object] is not a function
无论如何我注意到文档说 children
是只读的。
有没有简单的方法可以做到这一点? (关于动态对象管理的 documentation 实际上只涵盖了子对象的创建和销毁。)
根据 Mitch 的回答,我想到了这个:
function reorder() {
for (var i=0;i<children.length;i++) {
var index=columns*children[i].Layout.row + children[i].Layout.column;
var newIndex=(index+1)%(rows*columns);
children[i].Layout.row=Math.floor(newIndex/columns)%rows;
children[i].Layout.column=newIndex%columns;
}
}
有几点注意事项:
- 要使其正常工作,您必须已经在包含的项目上明确设置了
Layout.row
和 Layout.column
。如果您依赖 GridLayout
的单元格分配,附加属性将保持为零。这有点令人惊讶,因为我最初读到 documentation 暗示如果您不这样做,GridLayout 实际上会自行设置它们。
- 您还需要在布局上显式设置
rows
和 columns
(对于从左到右的布局,您可以只设置用于布局环绕目的的列...但是随后rows 属性 无论添加多少行子项都保持-1,上面的代码将失败。
- 随着项目的移动,它会发出一些控制台警告,例如
QGridLayoutEngine::addItem: Cell (1, 1) already taken
。不过好像够害人了。
- 显然,以上内容只是真正希望处理完全填充的单个单元格项目网格。
您可以通过更改 GridLayout 中项目的父级来执行最初描述的 pop/push-like 操作。从 GridLayout 中 un-parenting 从 GridLayout 中的任何索引弹出任何项目。通过 re-parenting 将其推到 GridLayout 的末尾再次到 GridLayout。在这两个操作之间,您可以通过按特定顺序推入和弹出所有子项来在任何位置插入项目,而不必在每个项目上管理 row/column,将自动布局留给 GridLayout。
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.9
import QtQuick.Layouts 1.3
Window {
id: window
visible: true
height: 600
width: 800
GridLayout {
id: grid
columns: 4
Rectangle {
id: rect1
color: Qt.rgba(Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, 1)
height: 20
width: 20
}
Rectangle {
id: rect2
color: Qt.rgba(Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, 1)
height: 20
width: 20
}
Rectangle {
id: rect3
color: Qt.rgba(Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, 1)
height: 20
width: 20
}
Rectangle {
id: rect4
color: Qt.rgba(Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, 1)
height: 20
width: 20
}
Rectangle {
id: rect5
color: Qt.rgba(Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, 1)
height: 20
width: 20
}
}
Item {
id: item
visible: false
}
Button {
text: "push first item to rear of gridview"
anchors.bottom: parent.bottom
onClicked: {
var object = grid.children[0]
object.parent = item // pop from grid
object.parent = grid // push to grid
}
}
}
如何重新排序 GridLayout(或其他 QML 项目容器)中的项目?我有一个有一定数量的行和列,并填充了子项。直到几分钟前,我还希望我可以简单地操作项目的 children
列表成员来重新排序它们:我在 UI 中有一个 MouseArea
按钮,我希望从中可以只需调用(来自 onClicked:
)a
function reorder() {children.unshift(children.pop());}
布局项的方法(意图是布局中的最后一项成为第一项),但触发时会生成错误消息:
TypeError: Property 'pop' of object [object Object] is not a function
无论如何我注意到文档说 children
是只读的。
有没有简单的方法可以做到这一点? (关于动态对象管理的 documentation 实际上只涵盖了子对象的创建和销毁。)
根据 Mitch 的回答,我想到了这个:
function reorder() {
for (var i=0;i<children.length;i++) {
var index=columns*children[i].Layout.row + children[i].Layout.column;
var newIndex=(index+1)%(rows*columns);
children[i].Layout.row=Math.floor(newIndex/columns)%rows;
children[i].Layout.column=newIndex%columns;
}
}
有几点注意事项:
- 要使其正常工作,您必须已经在包含的项目上明确设置了
Layout.row
和Layout.column
。如果您依赖GridLayout
的单元格分配,附加属性将保持为零。这有点令人惊讶,因为我最初读到 documentation 暗示如果您不这样做,GridLayout 实际上会自行设置它们。 - 您还需要在布局上显式设置
rows
和columns
(对于从左到右的布局,您可以只设置用于布局环绕目的的列...但是随后rows 属性 无论添加多少行子项都保持-1,上面的代码将失败。 - 随着项目的移动,它会发出一些控制台警告,例如
QGridLayoutEngine::addItem: Cell (1, 1) already taken
。不过好像够害人了。 - 显然,以上内容只是真正希望处理完全填充的单个单元格项目网格。
您可以通过更改 GridLayout 中项目的父级来执行最初描述的 pop/push-like 操作。从 GridLayout 中 un-parenting 从 GridLayout 中的任何索引弹出任何项目。通过 re-parenting 将其推到 GridLayout 的末尾再次到 GridLayout。在这两个操作之间,您可以通过按特定顺序推入和弹出所有子项来在任何位置插入项目,而不必在每个项目上管理 row/column,将自动布局留给 GridLayout。
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.9
import QtQuick.Layouts 1.3
Window {
id: window
visible: true
height: 600
width: 800
GridLayout {
id: grid
columns: 4
Rectangle {
id: rect1
color: Qt.rgba(Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, 1)
height: 20
width: 20
}
Rectangle {
id: rect2
color: Qt.rgba(Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, 1)
height: 20
width: 20
}
Rectangle {
id: rect3
color: Qt.rgba(Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, 1)
height: 20
width: 20
}
Rectangle {
id: rect4
color: Qt.rgba(Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, 1)
height: 20
width: 20
}
Rectangle {
id: rect5
color: Qt.rgba(Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, Math.random()*0.5 + 0.25, 1)
height: 20
width: 20
}
}
Item {
id: item
visible: false
}
Button {
text: "push first item to rear of gridview"
anchors.bottom: parent.bottom
onClicked: {
var object = grid.children[0]
object.parent = item // pop from grid
object.parent = grid // push to grid
}
}
}