c++ - C++ 中的 Qt Quick / QML 标志更改回 UI
问题描述
我对 Qt 很熟悉,但我可以在 QML/QTQuick 与 C++ 的交互中使用一些指导。我觉得我在这里遗漏了一些简单的东西,但有点卡住了。
我正在开发一个嵌入式系统,显示在串行总线上通信的分布式交换机的状态。串行总线在 C++(一直是 Qt)中作为单独的线程运行,并以循环方式自动轮询设备以从设备获取更新。
对此,我发现了一个非常简单的示例,它使用 QAbstractList 模型通过支持的 C++ 中的 QML 属性共享状态。https://www.youtube.com/watch?v=9BcAYDlpuT8&list=PLo12gBvZwC78nnrZHCBowKf36ZAi7iOLW&index=4&t=0s
最初模型看起来很棒,我只是加载了一个包含我需要的信息的列表,并且可以从 UI 中看到它。问题是,我如何从 C++ 访问模型,以便在后台更改时让更新冒泡到 UI。
到目前为止我所做的:
注册型号:
qmlReisterType<ModelDerrivedClass>("DeviceListModel",1,0,"DeviceList")
定义角色:
enum {
OpenRole = Qt::UserRole,
StatusRole
}
为模型定义哈希表
QHash<int,QByteArray> ModelDerrivedClass::roleNames() const
{
QHash<int, QByteArray> names;
names[OpenRole] = "openstatus";
names[StatusRole] = "devicestatus";
return names;
}
使用适当的信息创建简单的结构列表,实施必要的方法等......从上到下就像一个魅力。
如何自下而上访问模型?这些设备将根据 UI 不需要知道的外部输入更新状态,但这些事件需要能够驱动前端。看起来几乎没有考虑到这种情况。
我还研究了使用 QML 注册设备类型,但无法弄清楚如何将 QML 对象链接到 C++ 对象,以便 READ/WRITE/NOTIFY 属性与列表中的各个 QML 对象一起使用。在这种情况下,我会将 OPEN 和 STATUS 注册为 QML 类型的属性,可以直接在 QML 代码中使用,但我需要将对象实例 int C++ 与 QML 对象实例相关联。这是 QAbstractListModel 需要解决的问题。
任何援助将不胜感激。
解决方案
你有两个选择,但我认为第一个更好:
选项 1:rootContext
您可以在 a 的 rootContext 上设置一个属性,该属性将在该 qmlQQMlEngine
引擎加载的每个 QML 文件中可用(请参阅Qt 文档):
QQuickView view;
view.rootContext()->setContextProperty("currentDateTime",
QDateTime::currentDateTime());
view.setSource(QUrl::fromLocalFile("MyItem.qml"));
view.show();
你应该有一个模型的实例:
ModelDerivedClass devices;
QQuickView view;
view.rootContext()->setContextProperty("devices", &devices);
view.setSource(QUrl::fromLocalFile("MyItem.qml"));
view.show();
您现在可以更改ModelDerivedClass
usingsetData
或您自己的方法。
顺便说一句,在此选项中,您不应注册为类型,而应注册为不可创建的类型:
qmlRegisterUncreatableType<ModelDerrivedClass>("DeviceListModel",1,0,"DeviceList", "available as rootContext property 'devices'");
选项 2:单例
您可以制作ModelDerivedClass
一个 Singleton,它只能使用一次。在类中添加一个instance
函数:
class ModelDerivedClass
{
...
ModelDerivedClass* instance() {
static ModelDerivedClass theInstance;
return &theInstance;
}
...
}
您可以使用 C++ModelDerivedClass::instance()
来操作更改。
您还应该将其作为单例注册到 QML:
qmlRegisterSingletonType<ModelDerivedClass>("DeviceListModel", 1, 0, "DeviceList",
[](QQmlEngine *eng, QJSEngine *js) -> QObject*
{
return ModelDerivedClass::instance();
});
但是在这种情况下,您对对象的生命周期没有太多控制权,这可以说是不好的(可以在这个主题上找到很多讨论)。所以我建议采取选项1。
推荐阅读
- flutter - Flutter - 如何根据 JSON 数据更改 itemCount?
- reactjs - 如何在 React 中使用过滤器和保存状态值?
- r - 将栅格图层转换为 spatstat 对象
- java - 无法解决 没有为参数 1 指定值
- tensorflow - tf2.0中Sendex教程修改TensorBoard
- logstash - 如何在logstash中重新启动多个conf文件
- r - 根据它们是在两个值之间还是低于一个值来更改数据框中的条目
- ssis - 从 SSMS 运行 DTEXEC 以运行 SSIS 目录包
- neo4j - Neo4j:弱连接组件(WCC),仅将大网络保留在内存图中
- javascript - Artillery.io 总是返回失败:ensure.p95 < 200