Reputation: 24892
How can I reorder the items in a GridLayout (or other QML item containers generally)? I have one with some number of rows and columns and populated with child items. Until a few minutes ago I was hoping I could simply operate on the children
list member of the item to reorder them: I have a MouseArea
button in the UI from which I was hoping could simply invoke (from onClicked:
) a
function reorder() {children.unshift(children.pop());}
method of the layout item (with the intention of the last item in the layout becoming the first), but when triggered that generates the error message:
TypeError: Property 'pop' of object [object Object] is not a function
and in any case I note the documentation says children
is read only.
Is there an easy way of doing this? (The documentation on dynamic object management doesn't really cover more than creation and destruction of child objects.)
Upvotes: 3
Views: 4009
Reputation: 1738
You can do pop/push-like operations as initially described by changing the parent of the items in the GridLayout. Pop any item from any index in the GridLayout by un-parenting it from the GridLayout. Push to the end of the GridLayout by re-parenting it to the GridLayout again. Between these two operations, you could insert items at any location by pushing and popping all of the children in a specific order and not otherwise have to manage row/column on each item, leaving automatic layout to the 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
}
}
}
Upvotes: 2
Reputation: 24892
Following Mitch's answer, I came up with this:
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;
}
}
There are a few caveats:
Layout.row
and Layout.column
on the contained items already. If you rely on the GridLayout
's cell assignment, the attached properties remain zero. This was a bit surprising as I initially read the documentation as implying the GridLayout actually set these itself if you didn't.rows
and columns
on the layout explicitly (for left to right layouts you can get away with just setting columns for layout wrapping purposes... but then the rows property remains -1 regardless of how many rows of child items are added, and the above code will fail).QGridLayoutEngine::addItem: Cell (1, 1) already taken
as the items are shuffled along. Seems to be harmess enough though.Upvotes: 2