【问题标题】:How to create new instance of a Q_GADGET struct in QML?如何在 QML 中创建 Q_GADGET 结构的新实例?
【发布时间】:2017-08-05 11:02:19
【问题描述】:

我可以使用带有 Q_GADGET 标记的结构从 C++ 到 QML 发出信号。

是否可以将这样的结构从 QML 发送到 C++ 插槽?我的代码在第一步失败:在 QML 中创建一个实例。

此代码在第一行失败...

var bs = new BatteryState()
bs.percentRemaining = 1.0
bs.chargeDate = new Date()
DataProvider.setBatteryState(bs)

...有错误:

qrc:///main.qml:34: ReferenceError: BatteryState is not defined

我可以将 BatteryStatus 结构从 C++ 发送到 QML,但我想将一个作为单个参数发送回插槽。

这是 BatteryState.h 和 BatteryState.cpp:

// BatteryState.h
#pragma once

#include <QDate>
#include <QMetaType>

struct BatteryState
{
    Q_GADGET
    Q_PROPERTY(float percentRemaining  MEMBER percentRemaining)
    Q_PROPERTY(QDate date              MEMBER date)

public:
    explicit BatteryState();
    BatteryState(const BatteryState& other);
    virtual ~BatteryState();
    BatteryState& operator=(const BatteryState& other);
    bool operator!=(const BatteryState& other) const;
    bool operator==(const BatteryState& other) const;

    float percentRemaining;
    QDate date;
};
Q_DECLARE_METATYPE(BatteryState)

// BatteryState.cpp
#include "BatteryState.h"

BatteryState::BatteryState()
    : percentRemaining(), date(QDate::currentDate())
{}

BatteryState::BatteryState(const BatteryState& other)
    : percentRemaining(other.percentRemaining),
      date(other.date)
{}

BatteryState::~BatteryState() {}

BatteryState&BatteryState::operator=(const BatteryState& other)
{
    percentRemaining = other.percentRemaining;
    date = other.date;
    return *this;
}

bool BatteryState::operator!=(const BatteryState& other) const {
    return (percentRemaining != other.percentRemaining
            || date != other.date);
}

bool BatteryState::operator==(const BatteryState& other) const {
    return !(*this != other);
}

我在main.cpp中注册了这个类型:

qRegisterMetaType<BatteryState>();

建议?

【问题讨论】:

标签: c++ qt struct qml signals-slots


【解决方案1】:

您不要在 QML 中创建 Q_GADGETs,QML 对象必须是 QObject 派生的,并且不是通过 new 创建的 - 这仅适用于 JS 对象。小工具只是生成元数据,以便您可以从 QML 访问它们的成员等并传递,仅此而已。

是否可以将这样的结构从 QML 发送到 C++ 插槽?

可以发送,但不会在 QML 中创建。它可以从 C++ 函数返回给 QML,也可以作为某个对象的属性公开。

struct Test {
    Q_GADGET
    Q_PROPERTY(int test MEMBER test)
  public:
    Test() : test(qrand()) {}
    int test;
    Q_SLOT void foo() { qDebug() << "foo"; }
};

class F : public QObject { // factory exposed as context property F
    Q_OBJECT
  public slots:
    Test create() { return Test(); }
    void use(Test t) { qDebug() << t.test; }
};


    // from QML
    property var tt: F.create()

    Component.onCompleted: {
      F.use(F.create()) // works
      var t = F.create()
      console.log(t.test) // works
      F.use(t) // works
      console.log(tt.test) // works
      F.use(tt) // works
      tt.test = 555
      F.use(tt) // works
      t.test = 666
      F.use(t) // works
      t.foo() // works
    }

【讨论】:

  • 我有一个问题。我尝试了很多以这种方式自动完成的方法,但没有成功。例如,如果我输入 t。 +(ctrl+space) 没有结构成员的选项。怎么能这样?
  • 我怀疑您目前可以做些什么。希望随着时间的推移,Creator 能够更好地在 QML 中提供自动完成功能。
  • 这导致unknown type 错误。您需要使用Q_DECLARE_METATYPE() 声明它并使用qRegisterMetaType&lt;&gt;() 注册它。 see this answer
  • 您可以使用在 QML 中注册为可访问的 C++ 工厂对象和该工厂中的 Q_INVOKABLE 函数在 QML 中创建 Q_GADGETS,该函数返回 Q_GADGET 对象的实例。它返回的对象也应该是工厂类的成员。然后可以通过 Q_INVOKABLE 函数将该对象从 QML 传递到 C++。您甚至可以使用以下语法将 Q_GADGET 对象存储为 QML 属性:property var my_property: my_factory.makeQGadgetObject()
猜你喜欢
  • 1970-01-01
  • 2015-04-08
  • 2021-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
相关资源
最近更新 更多