从高度动态的 C++ 数据模型更新 QML:计时器与属性绑定

Posted

技术标签:

【中文标题】从高度动态的 C++ 数据模型更新 QML:计时器与属性绑定【英文标题】:Updating QML from highly dynamic C++ data model: Timer vs Property binding 【发布时间】:2017-07-28 04:39:30 【问题描述】:

假设一个 C++ 业务模型可能会非常快速地更改其基础数据(假设高达 1000 Hz)。 在我的具体情况下,这将是围绕在其自己的线程中运行的网络数据回调机制(更准确地说是 ROS 订阅者)的包装器。将数据视为一些传感器读数。进一步假设我们正在处理简单的数据,例如最坏情况下是单个双精度值或字符串。

在 QML 组件中可视化此类数据的最佳方式是什么?最好的一点是对资源的温和处理,最大限度地减少模型状态和视图之间的延迟,以及尽可能简洁的代码?

我想出了以下选项:

    将数据作为模型的属性绑定到视图,并在每次更新数据时发出 dataChanged() 信号:

    Pro:优雅的代码,在数据更新率低的情况下资源使用率最低。 Con:高信号频率会向 GUI 发送垃圾邮件并最大限度地利用资源,可能会导致系统无响应。

    使用 QML-Timer 并以特定间隔(例如 10 - 60 Hz)轮询模型:

    专业版:资源利用率上限,稳定率 Con:定时器本身消耗资源;不如数据绑定优雅;如果数据生成/回调速率低于定时器速率,则必须进行不必要的轮询调用。

    使用 1 中的数据绑定。但使用 QTimer(或其他计时器,如 boost's)限制 C++ 模型内的信号发射频率,即仅以特定间隔发射 dataChanged() 信号:

    专业版:同2。 缺点:同 2。

    结合 3. 中的 Timer 与某种检查数据是否实际发生变化,在发出信号之前,从而避免在数据没有变化时发出不必要的信号:

    专业版:同3。 Con:与 3 相同,但更不优雅;由于逻辑更复杂,导致错误的风险增加;模型更难重用,因为数据更改检查高度依赖于数据的性质

我是否错过了一个选项(除了一开始没有产生这么多数据)?您的选择或实现这一点的最 QT/QML 方式是什么?

【问题讨论】:

我不太确定我是否理解您的选项 4。仅在数据发生更改时发出 dataChanged() 对我来说听起来像是基本情况。 我过去曾使用过这种模式的变体:accu.org/index.php/journals/2589(它可以很好地结合基于推送的模型更新和 UI 节流轮询) 【参考方案1】:

首先,您确定存在性能问题吗?

我的意思是说,每秒 1000 次更新已经足够了,但这可能会强制 GUI 每秒更新 1000 次吗?或者 GUI 可能只在渲染新帧时更新?任何远程理智的 GUI 框架都可以做到这一点。即使您的数据每秒更改无数次,GUI 更改也只会以 GUI 正在呈现的帧速率反映。

话虽如此,您可以努力减少后端的压力。一个典型的“便利”实现会给系统带来负担,即使 Qt 支持的任何现代平台都可以为一两个对象处理 1000 Hz,如果这些对象很多,那么你应该努力减少它。即使不直接损害系统性能,只要开发成本不高,效率总是不错的。

我不建议使用属性或模型接口直接更新数据,因为这会充斥着信号通知。您应该在低级别静默处理底层数据更新,并且只定期通知属性或模型接口更改。

如果您的更新是连续的,只需设置一个计时器,如果有人在看它,30 Hz 甚至更低就可以了。

如果不是,您可以使用“脏”标志。当数据发生变化时,设置标志并单次启动更新定时器,当定时器触发并通知更新时,清除标志并暂停。这样您就可以避免在不需要任何更新的情况下运行计时器。

【讨论】:

以上是关于从高度动态的 C++ 数据模型更新 QML:计时器与属性绑定的主要内容,如果未能解决你的问题,请参考以下文章

Qt5 - 在 QML TableView 中显示动态数据模型

QML 创建 TreeView 动态模型的正确方法是啥?

删除 c++ 模型,使用 SetContextProperty 在 qml 中注册

使用多个视图在 QML 中查看、编辑和更新数据(来自 C++),而数据保留在 C++ 中(订阅数据)

QML TableView + QAbstractTableModel - 如何从 QML 编辑模型数据?

如何将 QPixmap 从 C++ 模型传递到 QML?