是否可以在 QML 列表视图中仅显示某些索引或一系列索引?
我有一个列表模型,其中包含我正在重用的大量信息。例如,是否可以有一个仅显示索引 5 到 8 的列表?
提出一种解决该问题的纯 QML 方法将会很有趣。当然,这不是最短的路径,但它是一个解决方案。 该方法基于
DelegateModel
models
。它在文档中写道:DelegateModel 类型封装了一个模型和将要执行的委托 为模型中的项目进行实例化。
通常不需要创建DelegateModel。然而,它可以 对于操作和访问 modelIndex 很有用 QAbstractItemModel 子类用作模型。另外,
DelegateModel 与 Package 一起使用为多个视图提供委托, 和 使用 DelegateModelGroup 来排序和过滤委托项目。
DelegateModel
确实是一个强大的类型,具有很多功能(有关详细信息,请参阅链接文档)。
DelegateModel
的两个关键属性是 groups
和
filterOnGroup
。前者基本上是一个
DelegateModelGroup
列表,它定义了要过滤或不过滤的项目。后者用于应用特定的过滤器,即通过简单地将属性设置为所选组的名称来选择 DelegateModelGroup
中包含的特定 groups
。请注意,引用
VisualDataModel
或
DelegateModel
是相同的,因为第一个是出于兼容性原因而提供的(这同样适用于 VisualDataGroup
w.r.t. DelegateModelGroup
)。总结一下,可以通过这种方式过滤完整 QML 中的模型:
创建
model
model
VisualDataModel
/DelegateModel
定义一个 VisualDataGroup
DelegateModelGroup
(或多个) - includeByDefault
设置为 false
以避免自动添加原始模型中的 all项目 定义填充组的策略
filterOnGroup
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");
}
}
}
}
}
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 );
DelegateModel
的答案:
实现两个 DelegateModelGroups"all"
"visible"
“全部”属性组将包含源模型中的所有记录role
from
和 to
属性(用于属性绑定)每当任何属性发生更改时,它都会调用 update()
update()
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)
}
}
}
}
您可以在线尝试!