Reputation: 1125
I want to create a reusable component where I could pass a model i.e.
["red", "green", "blue", "black", "orange", "pink", "gray", "navy", "magenta"]
And it would fill Grid
with rectangles of model data. And if there are more than let's say 6 items in model it would then fill other "page".
That's how it should look like:
Currently I use StackLayout
have 2 Grid
items and Repeater
inside of them and I divided my model into 2:
model: ["red", "green", "blue", "black", "orange", "pink"]
model: ["gray", "navy", "magenta"]
To fill each "page" with rectangles.
Writing logic to dynamically separate model into separate parts for each page seems overly complicated.
I have tried GridView
but I couldn't find important properties like in Grid
:
topPadding: 10
bottomPadding: 10
leftPadding: 20
rightPadding: 20
spacing: 10
columns: 2
Source of my example:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Rectangle {
id: mainArea
width: 400
height: 400
color: "beige"
StackLayout {
id: stackLayout
anchors.fill: parent
currentIndex: 0
Grid {
anchors.fill: parent
topPadding: 10
bottomPadding: 10
leftPadding: 20
rightPadding: 20
spacing: 10
columns: 2
property int maxRows: 3
Repeater {
model: ["red", "green", "blue", "black", "orange", "pink"]
Rectangle {
width: (parent.width - parent.leftPadding - parent.rightPadding - parent.spacing) / parent.columns
height: (parent.height - parent.topPadding - parent.bottomPadding - (parent.maxRows - 1) * parent.spacing) / parent.maxRows
color: modelData
}
}
}
Grid {
anchors.fill: parent
topPadding: 10
bottomPadding: 10
leftPadding: 20
rightPadding: 20
spacing: 10
columns: 2
property int maxRows: 3
Repeater {
model: ["gray", "navy", "magenta"]
Rectangle {
width: (parent.width - parent.leftPadding - parent.rightPadding - parent.spacing) / parent.columns
height: (parent.height - parent.topPadding - parent.bottomPadding - (parent.maxRows - 1) * parent.spacing) / parent.maxRows
color: modelData
}
}
}
}
}
Button {
anchors.bottom: mainArea.verticalCenter
anchors.bottomMargin: 5
anchors.left: mainArea.right
text: "<"
onClicked: stackLayout.currentIndex = 0
}
Button {
anchors.top: mainArea.verticalCenter
anchors.topMargin: 5
anchors.left: mainArea.right
text: ">"
onClicked: stackLayout.currentIndex = 1
}
}
Upvotes: 0
Views: 1024
Reputation: 13711
For a simple array, you can use the method array.slice(from, to)
to create models for each page.
property int page: 0
Button {
text: "up"
onClicked: page++
}
Grid {
y: 100
rows: 2
columns: 2
Repeater {
model: ["red", "green", "blue", "black", "orange", "pink", "gray", "navy", "magenta", "yellow", "cyan", "brown", "lightblue", "darkred"].slice(page * 4, (page + 1) * 4)
Rectangle {
width: 100
height: 100
color: modelData
}
}
}
For QAbstractItemModel
-descendents, you can use the method explained here if you want to have a QML-only solution.
Otherwise you might implement a faster filter model in C++ utilizing the QSortFilterProxyModel
or maybe the QIdentityProxyModel
See this implementation by GrecKo for a possible way, how to get the SortFilterProxyModel
working in QML.
Upvotes: 2
Reputation: 49329
You could try filtering the model to show only specific indices.
Or even simpler, you can simply set the delegate visibility depending on the index and items per page:
ApplicationWindow {
id: main
visible: true
width: 640
height: 480
color: "darkgray"
property int maxRows: 3
property int page: 0
property int iperp: 2 * maxRows
Grid {
anchors.fill: parent
topPadding: 10
bottomPadding: 50
leftPadding: 20
rightPadding: 20
spacing: 10
columns: 2
Repeater {
id: rep
model: ["red", "green", "blue", "black", "orange", "pink", "gray", "navy", "magenta", "yellow", "cyan", "brown", "lightblue", "darkred"]
Rectangle {
width: (parent.width - parent.leftPadding - parent.rightPadding - parent.spacing) / parent.columns
height: (parent.height - parent.topPadding - parent.bottomPadding - (maxRows - 1) * parent.spacing) / maxRows
color: modelData
visible: {
var i = page * iperp
return index >= i && index < i + iperp
}
Text {
anchors.centerIn: parent
text: index
}
}
}
}
Row {
anchors.horizontalCenter: main.contentItem.horizontalCenter
anchors.bottom: main.contentItem.bottom
Button {
text: "<<"
enabled: page
onClicked: --page
}
Button {
text: ">>"
enabled: page < rep.count / iperp - 1
onClicked: ++page
}
}
}
Upvotes: 2