将采用模型并将其显示在以页面分隔的网格中的 Qt 组件

Qt component that would take model and display it in grid separated in pages

我想创建一个可重用的组件,我可以在其中传递模型,即

["red", "green", "blue", "black", "orange", "pink", "gray", "navy", "magenta"]

它会用模型数据的矩形填充 Grid。如果模型中的项目超过 6 个,那么它将填充其他 "page".

它应该是这样的:

目前我使用 StackLayout 有 2 个 Grid 项目和 Repeater 在他们里面,我把我的模型分成 2:

model: ["red", "green", "blue", "black", "orange", "pink"]
model: ["gray", "navy", "magenta"]

用矩形填充每个 "page"。

为每个页面动态地将模型分成单独的部分的编写逻辑似乎过于复杂。 我试过 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
    }
}

您可以尝试过滤模型以仅显示特定索引。

或者更简单,您可以根据每页的索引和项目简单地设置委托可见性:

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
    }
  }
}

对于简单的数组,您可以使用方法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-后代,如果您想要一个仅 QML 的解决方案,您可以使用解释的方法

否则,您可能会利用 QSortFilterProxyModel 或者 QIdentityProxyModel

在 C++ 中实现更快的过滤器模型

请参阅 GrecKothis 实现,了解如何使 SortFilterProxyModel 在 QML 中工作的可能方法。