如何重新排序 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 实际上只涵盖了子对象的创建和销毁。)

您可以使用 row and column 附加属性。

根据 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.rowLayout.column。如果您依赖 GridLayout 的单元格分配,附加属性将保持为零。这有点令人惊讶,因为我最初读到 documentation 暗示如果您不这样做,GridLayout 实际上会自行设置它们。
  • 您还需要在布局上显式设置 rowscolumns(对于从左到右的布局,您可以只设置用于布局环绕目的的列...但是随后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
        }
    }
}