如何在QML中创建一个Q_GADGET结构体的新实例?

7

我可以使用带有 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

我可以从C++向QML发出一个BatteryStatus结构,但我想将其作为单个参数发送回插槽。
这是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>();

建议?

请查看此链接了解如何注册可实例化对象类型,文档地址为:http://doc.qt.io/qt-5/qtqml-cppintegration-definetypes.html#registering-an-instantiable-object-type - bipll
1个回答

11
您不需要在QML中创建Q_GADGET,QML对象需要派生自QObject,并且不会通过new创建 - 这仅适用于JS对象。Gadgets只是生成元数据,以便您可以从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),没有结构成员的选项。我该怎么做? - CMLDMR
我怀疑目前你无法做任何事情。希望在未来,Creator能够更好地提供 QML 的自动完成功能。 - dtech
这会导致“未知类型”错误。您需要使用Q_DECLARE_METATYPE()进行声明,并使用qRegisterMetaType<>()进行注册。请参见此答案 - S.M.Mousavi
你可以使用在QML中注册为可访问的C++工厂对象和一个在该工厂中返回Q_GADGET对象实例的Q_INVOKABLE函数,在QML中创建Q_GADGETS。它返回的对象也应该是工厂类的成员。通过Q_INVOKABLE函数,你甚至可以将这个对象从QML传递到C++。你可以使用以下语法将一个Q_GADGET对象作为QML属性存储:property var my_property: my_factory.makeQGadgetObject()。 - aatwo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接