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

问题描述 投票:0回答:4

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

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

qt listview qml
4个回答
19
投票

提出一种解决该问题的纯 QML 方法将会很有趣。当然,这不是最短的路径,但它是一个解决方案。 该方法基于

DelegateModel

QML 模块中提供的

models
。它在文档中写道:

DelegateModel 类型封装了一个模型和将要执行的委托 为模型中的项目进行实例化。

通常不需要创建DelegateModel。然而,它可以 对于操作和访问 modelIndex 很有用 QAbstractItemModel 子类用作模型。另外,

DelegateModel 与 Package 一起使用

为多个视图提供委托, 和 使用 DelegateModelGroup 来排序和过滤委托项目

DelegateModel

确实是一个强大的类型,具有很多功能(有关详细信息,请参阅链接文档)。

DelegateModel
的两个关键属性是
groups
filterOnGroup
。前者基本上是一个 
DelegateModelGroup
列表,它定义了要过滤或不过滤的项目。后者用于应用特定的过滤器,即通过简单地将属性设置为所选组的名称来选择
DelegateModelGroup
中包含的特定
groups

请注意,引用

VisualDataModel

DelegateModel
是相同的,因为第一个是出于兼容性原因而提供的(这同样适用于
VisualDataGroup
w.r.t.
DelegateModelGroup
)。

总结一下,可以通过这种方式过滤完整 QML 中的模型:

创建
    model
  1. 作为过滤模型的来源
  2. model
  3. 喂入
    VisualDataModel
    /
    DelegateModel
    定义一个 
  4. VisualDataGroup
  5. /
    DelegateModelGroup
    (或多个) -
    includeByDefault
    设置为
    false
    以避免自动添加原始模型中的
    all
    项目 定义填充组的策略
  6. filterOnGroup
  7. 设置为所选组
    将视图模型设置为 
  8. VisualDataModel
  9. 模型
    
    
    
  10. 在下一个示例中,为简单起见,我仅在
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"); } } } } }



3
投票
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 );



3
投票

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

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


1
投票
DelegateModel

的答案:


实现两个 DelegateModelGroups
    "all"
  1. "visible"
    “全部”属性组将包含源模型中的所有记录
  2. “可见”属性组将包含记录的子选择
  3. 此外,我还实现了
  4. role
  5. from
    to
    属性(用于属性绑定)
    每当任何属性发生更改时,它都会调用 
  6. update()
  7. 方法
    每当调用 
  8. update()
  9. 时,都会重新扫描“所有”组,并且仅将匹配/过滤的记录放置在“可见”组中
    
    
  10. 为了演示这一点,我将 8 只动物放入
ListModel

中。我定义了一个

RangeSlider
来控制
from
to
参数,这些参数将控制我想在
DelegateModel
中看到哪些元素。:
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Page {
    ListModel {
        id: animals
        ListElement { aid: 1; animal: "Aardvark" }
        ListElement { aid: 2; animal: "Bear" }
        ListElement { aid: 3; animal: "Cat" }
        ListElement { aid: 4; animal: "Dog" }
        ListElement { aid: 5; animal: "Eagle" }
        ListElement { aid: 6; animal: "Fruitbat" }
        ListElement { aid: 7; animal: "Goat" }
        ListElement { aid: 8; animal: "Hedgehog" }
    }
    ColumnLayout {
        anchors.fill: parent
        Label { text: qsTr("Select Range") }
        RangeSlider { id: range; from: 1; to: 8; first.value: 3; second.value: 8 }
        Label { text: qsTr("Animals %1 .. %2").arg(range.first.value).arg(range.second.value) }
        ListView {
            Layout.fillWidth: true
            Layout.fillHeight: true
            model: DelegateModel {
                model: animals
                property string role: "aid"
                property real from: range.first.value
                property real to: range.second.value
                onRoleChanged: Qt.callLater(update)
                onFromChanged: Qt.callLater(update)
                onToChanged: Qt.callLater(update)
                delegate: Rectangle {
                    width: ListView.view.width
                    height: 28
                    color: DelegateModel.visibleIndex & 1 ? "#eee" : "#ccc"
                    Label {
                        anchors { left: parent.left; verticalCenter: parent.verticalCenter; margins: 5 }
                        text: `${aid} ${animal}`
                    }
                }
                groups: [
                    DelegateModelGroup { id: allItems; name: "all"; includeByDefault: true },
                    DelegateModelGroup { name: "visible" }
                ]
                filterOnGroup: "visible"
                function update() {
                    allItems.setGroups(0, allItems.count, [ "all" ] );
                    for (let index = 0; index < allItems.count; index++) {
                        const item = allItems.get(index).model;
                        const visible = item[role] >= from && item[role] <= to;
                        if (!visible) continue;
                        allItems.setGroups(index, 1, [ "all", "visible" ]);
                    }
                }
                Component.onCompleted: Qt.callLater(update)
            }
        }
    }
}

您可以
在线尝试!

© www.soinside.com 2019 - 2024. All rights reserved.