QML需要创建具有bool属性的组件,所有列表元素都在限制范围内



我想我需要一个类似于 ListModel 的组件,但我需要扩展它以公开一个只读布尔属性,例如"所有列表元素都在最小和最大限制内",这样我就可以在组件之外执行逻辑来确定某些事情。我应该如何根据模型的内容扩展布尔属性?

我想天真的方法是只添加 qml 属性并在 QML 端执行 javascript 循环以检查所有模型内容,但这可能不是那么好的性能

你考虑过DelegateModel吗?它允许您在ListModel上创建"视图",以便您可以通过filterOnGroup属性控制要显示的内容。

这很难理解,但是,在下面的示例中,我有一个包含 5 个城市的ListModel。当您开始更改范围滑块时,将根据所选的最小/最大人口过滤 5 个城市。这通过更新DelegateModel上的布尔函数过滤器来反映现在可见的城市。

property var filter: model => model.pop >= rangeSlider.first.value
&& model.pop <= rangeSlider.second.value

以下是完整的代码片段:

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQml.Models 2.15
Page {
anchors.fill: parent
ColumnLayout {
anchors.fill: parent
Label { text: qsTr("States") }
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
model: DelegateModel {
id: filterDelegateModel
property int updateIndex: 0
property var filter: model => model.pop >= rangeSlider.first.value
&& model.pop <= rangeSlider.second.value
onFilterChanged: Qt.callLater(update)
model: us_states
groups: [
DelegateModelGroup {
id: allItems
name: "all"
includeByDefault: true
onCountChanged: {
if (filterDelegateModel.updateIndex > allItems.count) filterDelegateModel.updateIndex = allItems.count;
if (filterDelegateModel.updateIndex < allItems.count) Qt.callLater(update, filterDelegateModel.updateIndex);
}
},
DelegateModelGroup {
id: visibleItems
name: "visible"
}]
filterOnGroup: "visible"
delegate: Frame {
id: frame
width: ListView.view.width - 20
background: Rectangle {
color: (frame.DelegateModel.visibleIndex & 1) ? "#f0f0f0" : "#e0e0e0"
border.color: "#c0c0c0"
}
RowLayout {
width: parent.width
Text {
text: (frame.DelegateModel.visibleIndex + 1)
color: "#808080"
}
Text {
Layout.fillWidth: true
text: model.state
}
Text {
text: qsTr("pop: %1 M").arg((pop / 1000000).toFixed(2))
}
}
}
function update(startIndex) {
startIndex = startIndex ?? 0;
if (startIndex < 0) startIndex = 0;
if (startIndex >= allItems.count) {
updateIndex = allItems.count;
return;
}
updateIndex = startIndex;
if (updateIndex === 0) {
allItems.setGroups(0, allItems.count, ["all"]);
}
for (let ts = Date.now(); updateIndex < allItems.count && Date.now() < ts + 50; updateIndex++) {
let visible = !filter || filter(allItems.get(filterDelegateModel.updateIndex).model);
if (!visible) continue;
allItems.setGroups(updateIndex, 1, ["all", "visible"]);
}
if (updateIndex < allItems.count) Qt.callLater(update, updateIndex);
}
Component.onCompleted: Qt.callLater(update)
}
}
Label { text: "Population Range" }
RangeSlider {
id: rangeSlider
Layout.fillWidth: true
from: 0
to: 100000000
first.value: 1
first.onMoved: Qt.callLater(filterDelegateModel.update)
second.value: 100000000
second.onMoved: Qt.callLater(filterDelegateModel.update)
stepSize: 1000000

}
Label { text: qsTr("Minimum %1 M").arg((rangeSlider.first.value / 1000000).toFixed(2))  }
Label { text: qsTr("Maximum %1 M").arg((rangeSlider.second.value / 1000000).toFixed(2)) }
}
ListModel {
id: us_states
ListElement { state:"California"; pop: 39350000 }
ListElement { state:"Texas"; pop: 28640000 }
ListElement { state:"New York"; pop: 8380000 }
ListElement { state:"Nevada"; pop: 3030000 }
ListElement { state:"Las Vegas"; pop: 644000 }
}
}

您可以在线试用!

我已将上述内容重构为FilterDelegateModel可重用的组件。随意查看:

  • https://github.com/stephenquan/qt5-qml-toolkit
  • https://github.com/stephenquan/qt5-qml-toolkit/wiki/FilterDelegateModel

最新更新