我有一个多态(如任意角色)QObject
模型,它主要是从 QML 以声明方式实例化的,as in this answer ,并且我希望能够拥有自定义数据“ View ”,通过任意的和可能的 - 从代码字符串 JS 仿函数生成的运行时对模型进行排序和过滤,类似的东西:
DataView {
sourceModel: model
filter: function(o) { return o.size > 3 }
sort: function(a, b) { return a.size > b.size }
}
QSortFilterProxyModel
接口(interface)似乎并不是特别适合这项任务,而是专注于静态角色和预编译规则。
我尝试在 C++ 端使用 QJSValue
属性,但似乎这是不可能的,C++ 代码无法使用该属性类型进行编译。如果我将属性类型设置为 QVariant
,我会从 QML 收到错误消息,指出函数只能绑定(bind)到 var
属性。显然,var
到 QVariant
的转换不会像返回值那样在此处启动。
最佳答案
正如您提到的,您可以使用 QJSValue。但这是相当静态的。如果你想使用像 filter: function(o) { return o.size > slider.value; 这样的过滤器怎么办? }
使用动态 slider ?您必须手动调用 invalidateFilter()
。
作为更实用的替代方法,您可以改用 QQmlScriptString
作为属性(property) & QQmlExpression
执行它。使用 QQmlExpression
允许您通过 setNotifyOnValueChanged
通知上下文更改.
你的语法会变成这样:filter: o.size > slider.value
。
如果您正在寻找开箱即用的解决方案,我已经在我的库中实现了它:SortFilterProxyModel on GitHub
可以看看ExpressionFilter
& ExpressionSorter
,那些与您最初想要的相同。您可以在 repo 中查看完整的源代码。
使用方法:
import SortFilterProxyModel 0.2
// ...
SortFilterProxyModel {
sourceModel: model
filters: ExpressionFilter { expression: model.size > 3 }
sorters: ExpressionSorter { expression: modelLeft.size < modelRight.size }
}
但正如@dtech 提到的那样,为模型的每一行在 qml 和 c++ 之间来回切换的开销非常明显。这就是我创建更具体的过滤器和分类器的原因。在您的情况下,我们将使用 RangeFilter
和 RoleSorter
:
import SortFilterProxyModel 0.2
// ...
SortFilterProxyModel {
sourceModel: model
filters: RangeFilter {
roleName: "size"
minimumValue > 3
minimumInclusive: true
}
sorters: RoleSorter { roleName: "size" }
}
这样做,我们就有了一个很好的声明式 API,参数只从 qml 传递到 c++ 一次。然后,所有过滤和排序都完全在 C++ 端完成。
关于c++ - 通过 QML 仿函数对 C++ 模型进行排序和过滤?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50689617/