c++ - 通过 QML 仿函数对 C++ 模型进行排序和过滤?

标签 c++ qt model qml filtering

我有一个多态(如任意角色)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 属性。显然,varQVariant 的转换不会像返回值那样在此处启动。

最佳答案

正如您提到的,您可以使用 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++ 之间来回切换的开销非常明显。这就是我创建更具体的过滤器和分类器的原因。在您的情况下,我们将使用 RangeFilterRoleSorter :

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/

相关文章:

c++ - 静态成员错误地初始化为空字符串

qt - QImage 写入时复制

ruby-on-rails - 我需要手动为我的外键字段添加索引还是 Rails 自动添加索引?

php - Yii2 如何将范围传递给搜索模型

c++ - 如何在 C++11 中有效地选择标准库容器?

c++ - 您如何抽象要在屏幕上显示的信息?

linux - 在 Windows 中字体显示为斜体,但在 Linux 中它始终显示为粗体

CakePHP 为不同类型的评论制作子模型

c++ - Foo *p = 0;p->p() 如何有效?

qt - 仅使用样式表部分设置背景颜色