首页 > 解决方案 > 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 需要解决的问题。

任何援助将不胜感激。

标签: c++qtqmlqtquick2

解决方案


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

选项 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();

您现在可以更改ModelDerivedClassusingsetData或您自己的方法。

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

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。


推荐阅读