我以前对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;
}用适当的信息创建简单的结构列表,然后实现必要的方法,etc...works就像自上而下的魅力。
如何从下到上访问模型?这些设备将根据UI不需要注意的外部输入来更新状态,但是这些事件需要能够驱动前端。看起来,这种情况似乎没有考虑到。
我还研究过用QML注册设备类型,但不知道如何将QML对象链接到C++对象,以便读/写/通知属性可以处理列表中的单个QML对象。在这个场景中,我会将OPEN和STATUS注册为QML类型的属性,这些属性可以直接在QML代码中使用,但我需要将对象实例int C++与QML对象实例关联起来。这是QAbstractListModel应用程序需要解决的问题。
如能提供任何协助,将不胜感激。
发布于 2020-04-30 19:28:05
你有两种选择,但我认为第一种更好:
选项1: rootContext
您可以在rootContext上设置一个QQMlEngine属性,该属性在该QML引擎加载的每个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或您自己的方法对setData进行更改。
顺便说一句,在这个选项中,您不应该注册类型,而应该注册为不可创建的类型:
qmlRegisterUncreatableType<ModelDerrivedClass>("DeviceListModel",1,0,"DeviceList", "available as rootContext property 'devices'");选项2:单例
您可以使ModelDerivedClass成为一个单例,它仅可用一次。向类添加一个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();
});但是在这种情况下,您对对象的生存期没有太多的控制,这可以说是不好的(可以找到很多关于这个主题的讨论)。所以我建议选择第一种选择。
发布于 2020-04-30 19:31:13
主要要认识到的是,主线程是一个特殊的线程,必须是唯一访问和更改GUI状态的线程。Qt和QML的大部分内容都是单线程的。
因此,您需要将更改从串行总线线程传递到主线程。这可以从串行总线线程连接插槽/信号到主线程上的适当对象。
Qt知道当您已经跨越了这样的连接的线程边界,并会将它以某种方式发布到主线程,以确保它以单线程的方式处理。
https://stackoverflow.com/questions/61530980
复制相似问题