首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Quick标志在C++中更改回UI

Quick标志在C++中更改回UI
EN

Stack Overflow用户
提问于 2020-04-30 19:09:16
回答 2查看 260关注 0票数 0

我以前对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。

我到目前为止所做的事:

注册模式:

代码语言:javascript
复制
qmlReisterType<ModelDerrivedClass>("DeviceListModel",1,0,"DeviceList")

定义角色:

代码语言:javascript
复制
   enum {
    OpenRole = Qt::UserRole,
    StatusRole
    }

为模型定义哈希表

代码语言:javascript
复制
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应用程序需要解决的问题。

如能提供任何协助,将不胜感激。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-30 19:28:05

你有两种选择,但我认为第一种更好:

选项1: rootContext

您可以在rootContext上设置一个QQMlEngine属性,该属性在该QML引擎加载的每个qml文件中都是可用的(参见Qt文档):

代码语言:javascript
复制
QQuickView view;
view.rootContext()->setContextProperty("currentDateTime", 
QDateTime::currentDateTime());
view.setSource(QUrl::fromLocalFile("MyItem.qml"));
view.show();

您应该有一个模型的实例:

代码语言:javascript
复制
ModelDerivedClass devices;

QQuickView view;
view.rootContext()->setContextProperty("devices", &devices);
view.setSource(QUrl::fromLocalFile("MyItem.qml"));
view.show();

现在可以使用ModelDerivedClass或您自己的方法对setData进行更改。

顺便说一句,在这个选项中,您不应该注册类型,而应该注册为不可创建的类型:

代码语言:javascript
复制
qmlRegisterUncreatableType<ModelDerrivedClass>("DeviceListModel",1,0,"DeviceList", "available as rootContext property 'devices'");

选项2:单例

您可以使ModelDerivedClass成为一个单例,它仅可用一次。向类添加一个instance函数:

代码语言:javascript
复制
class ModelDerivedClass
{
    ...
    ModelDerivedClass* instance() {
        static ModelDerivedClass theInstance;
        return &theInstance;
    }
    ...
}

在C++中,您可以使用ModelDerivedClass::instance()来操作更改。

您还应该将它注册到QML作为单例:

代码语言:javascript
复制
qmlRegisterSingletonType<ModelDerivedClass>("DeviceListModel", 1, 0, "DeviceList",
    [](QQmlEngine *eng, QJSEngine *js) -> QObject*
    {
        return ModelDerivedClass::instance();
    });

但是在这种情况下,您对对象的生存期没有太多的控制,这可以说是不好的(可以找到很多关于这个主题的讨论)。所以我建议选择第一种选择。

票数 0
EN

Stack Overflow用户

发布于 2020-04-30 19:31:13

主要要认识到的是,主线程是一个特殊的线程,必须是唯一访问和更改GUI状态的线程。Qt和QML的大部分内容都是单线程的。

因此,您需要将更改从串行总线线程传递到主线程。这可以从串行总线线程连接插槽/信号到主线程上的适当对象。

Qt知道当您已经跨越了这样的连接的线程边界,并会将它以某种方式发布到主线程,以确保它以单线程的方式处理。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61530980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档