将采用模型并将其显示在页面中分隔的网格中的 Qt 组件
Posted
技术标签:
【中文标题】将采用模型并将其显示在页面中分隔的网格中的 Qt 组件【英文标题】:Qt component that would take model and display it in grid separated in pages 【发布时间】:2017-09-19 11:04:34 【问题描述】:我想创建一个可重用的组件,我可以在其中传递模型,即
["red", "green", "blue", "black", "orange", "pink", "gray", "navy", "magenta"]
它会用模型数据的矩形填充Grid
。如果模型中有超过 6 个项目,它将填充其他“页面”。
它应该是这样的:
目前我使用 StackLayout
有 2 个 Grid
项目和 Repeater
在其中,我将我的模型分为 2:
model: ["red", "green", "blue", "black", "orange", "pink"]
model: ["gray", "navy", "magenta"]
用矩形填充每个“页面”。
为每个页面动态地将模型分成不同部分的编写逻辑似乎过于复杂。
我试过GridView
,但我找不到像Grid
这样的重要属性:
topPadding: 10
bottomPadding: 10
leftPadding: 20
rightPadding: 20
spacing: 10
columns: 2
我的例子来源:
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
【问题讨论】:
您想让模型成为数组还是ListModel
?
@derM 数组。我猜ListModel
会更复杂。
不过,您可以使用here 的解决方案......我在开始使用 QML 后不久就写了它,还有很多需要改进的地方。 DelegateModel
的使用可能会更快,如果您将其替换为 C++ ...ProxyModel
,例如 QSortFilterProxyModel
或 not-so-identity-proxymodel,但后者需要 ListModel
afaik。
【参考方案1】:
对于简单的数组,可以使用array.slice(from, to)
方法为每个页面创建模型。
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
对于QAbstractItemModel
-descendents,如果你想要一个仅QML的解决方案,你可以使用here解释的方法。
否则,您可能会利用 QSortFilterProxyModel
或 QIdentityProxyModel
在 C++ 中实现更快的过滤器模型
请参阅 GrecKo 的 this 实现,了解如何让 SortFilterProxyModel
在 QML 中工作。
【讨论】:
slice
ofc。我的错:-)【参考方案2】:
您可以尝试过滤模型以仅显示特定索引。
或者更简单,您可以根据每页的索引和项目简单地设置委托可见性:
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
【讨论】:
喜欢这个解决方案。我不喜欢我使用StackLayout
,所以这正是我想要的。
对于小型模型,这是一个简单的解决方案。对于大型模型,您将有 Rectangle
s 的大量开销。
Repeater
总是创建所有实例。 Grid
只是忽略所有 Item
s,没有尺寸或布局可见性。
(From Documentation) "如果 Grid 中的某个项目不可见,或者它的宽度或高度为 0,则该项目将不会被布局并且在其中不可见列。” 您可以将Grid
更改为GridView
并将contentItem
分区以始终显示正确的部分。
是的,我快速检查了一下,确实是这样。所有项目均已创建。尽管如此,对于不是很大的模型仍然非常有用。在实际生产中,我使用自己的代理模型,可以通过 JS 函子进行过滤和排序。以上是关于将采用模型并将其显示在页面中分隔的网格中的 Qt 组件的主要内容,如果未能解决你的问题,请参考以下文章