是否可以只显示 QML 列表视图的某些索引?

Is it possible to show only certain indexes of a QML listview?

是否可以在 QML 列表视图中仅显示某些索引或一系列索引?

我有一个列表模型,其中包含大量我正在重复使用的信息。是否可以有一个列表显示,例如,仅索引 5 到 8?

是的,这是可能的。您需要覆盖 QSortFilterProxyModel::filterAcceptRow 方法。

MyFilterModel::filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const
{
  if ( source_row > 5 && source_row < 8 )
    return true;

  return false;
}
//...
MyFilterModel *filter = new MyFilterModel();
filter->setSourceMoldel( yourSourceModel );
view->setModel( filter );

您可以通过在特定条件下将委托可见性设置为 false 来实现:

  Grid {
    anchors.fill: parent
    rows: 4
    columns: 5
    spacing: 5
    Repeater {
      model: 20
      delegate: Rectangle {
        width: 50
        height: 50
        visible: index >= 5 && index <= 8 // show only certain indices
        Text {
          anchors.centerIn: parent
          text: index
        }
      }
    }
  }

在内存中创建隐藏项目会产生一些开销,因此如果您处理非常大的模型并且只显示其中的一小部分,则不是最佳选择。

提出一个纯 QML 方法来解决这个问题会很有趣。当然,这不是 短路,但它是一个解决方案。

该方法基于 models QML 模块中可用的 DelegateModel。它在文档中读取:

The DelegateModel type encapsulates a model and the delegate that will be instantiated for items in the model.

It is usually not necessary to create a DelegateModel. However, it can be useful for manipulating and accessing the modelIndex when a QAbstractItemModel subclass is used as the model. Also, DelegateModel is used together with Package to provide delegates to multiple views, and with DelegateModelGroup to sort and filter delegate items.

DelegateModel 确实是一个功能强大的类型(有关详细信息,请参阅链接文档)。 DelegateModel 的两个关键属性是 groups and filterOnGroup。前者基本上是一个 DelegateModelGroup 的列表,它定义了要过滤或不过滤的项目。后者用于应用特定的过滤器,即通过简单地将 属性 设置为所选组的名称,选择包含在 groups 中的特定 DelegateModelGroup

请注意,引用 VisualDataModelDelegateModel 是相同的,因为第一个是出于兼容性原因提供的(同样适用于 VisualDataGroup w.r.t。DelegateModelGroup).

总而言之,可以通过这种方式在完整的 QML 中过滤模型:

  1. 创建一个 model 作为筛选模型的来源
  2. model 喂给 VisualDataModel/DelegateModel
  3. 定义一个VisualDataGroup/DelegateModelGroup(或多个)- includeByDefault设置为false以避免自动添加all 个来自原始模型的项目
  4. 定义填充组的策略
  5. filterOnGroup设置为所选组
  6. 将视图模型设置为 VisualDataModel 模型

在下一个示例中,为简单起见,我只在 Component.onCompleted 事件处理程序期间填充组一次。如前所述,应该选择策略,这取决于具体的用例。

在示例中,只有 key 角色等于 0 的项目被添加到 key0 组,即 ListView 中显示的组。上述清单在代码中突出显示。

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.0

ApplicationWindow {
    title: qsTr("DelegateModel test")
    width: 200
    height: 350
    visible: true

    ListView {
        id: displayListView
        anchors.fill: parent
        spacing: 5
        //
        model: displayDelegateModel             // 6
    }

    ListModel {                                 // 1
        id: myModel
        ListElement { vis: "One"; key: 0; }
        ListElement { vis: "two"; key: 1; }
        ListElement { vis: "Three"; key: 0; }
        ListElement { vis: "Four"; key: 0; }
        ListElement { vis: "Five"; key: 1; }
        ListElement { vis: "Six"; key: 1; }
        ListElement { vis: "Seven"; key: 0; }
    }

    VisualDataModel {
        id: displayDelegateModel

        delegate:  Rectangle {
            anchors.left: parent.left
            anchors.right: parent.right
            height: 25
            color: "steelblue"

            Text {
                text: vis
                anchors.centerIn: parent
                font.bold: true
                font.pixelSize: 20
            }
        }

        model: myModel                          // 2

        groups: [
            VisualDataGroup {                   // 3
                includeByDefault: false         // NECESSARY TO AVOID AUTOADDITION
                name: "key0"
            }
        ]

        filterOnGroup: "key0"                   // 5

        Component.onCompleted: {                // 4
            var rowCount = myModel.count;
            items.remove(0,rowCount);
            for( var i = 0;i < rowCount;i++ ) {
                var entry = myModel.get(i);
                if(entry.key == 0) {
                    items.insert(entry, "key0");
                }
            }
        }
    }
}