将 Q_GADGET 作为信号参数从 C++ 传递到 QML [英] Passing Q_GADGET as signal parameter from C++ to QML

查看:19
本文介绍了将 Q_GADGET 作为信号参数从 C++ 传递到 QML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

无法在 QML 代码中获取 C++ 对象的属性.对象作为参数传递给信号.

Can't get a property of a C++ object inside a QML code. Object is passed as a parameter to the signal.

期望在QML中,可以提取Record对象的text属性.并且值应该是abc.QML 将对象视为 QVariant(Record),并将其属性 text 视为 undefined.

Expected that in QML, the property text of the Record object can be extracted. And the value should be abc. QML sees the object as QVariant(Record), and its property text as undefined.

Record是类似QPoint的值类型,所以它使用Q_GADGET声明.

Record is a value-type like QPoint, so it uses Q_GADGET declaration.

hpp:

#ifndef LISTENP_HPP_
#define LISTENP_HPP_

#include <QObject>

#include "Record.hpp"

class ListenP: public QObject
{
Q_OBJECT

public:
    ListenP();
    virtual ~ListenP();

    void emitGotRecord();

signals:
    void gotRecord(Record r);
};

#endif /* LISTENP_HPP_ */

cpp:

#include "ListenP.hpp"

ListenP::ListenP() :
        QObject()
{
}

ListenP::~ListenP()
{
}

void ListenP::emitGotRecord()
{
    emit gotRecord(Record("abc"));
}

用于记录的hpp:

#ifndef RECORD_HPP_
#define RECORD_HPP_

#include <QObject>
#include <QMetaType>

class Record
{
Q_GADGET

Q_PROPERTY(QString text READ text WRITE setText)

public:
    Record(const QString& text = "");
    ~Record();

    QString text() const
    {
        return m_text;
    }

    void setText(const QString& text)
    {
        m_text = text;
    }

private:
    QString m_text;
};

Q_DECLARE_METATYPE(Record)

#endif /* RECORD_HPP_ */

用于记录的 cpp:

#include "Record.hpp"

Record::Record(const QString& text) :
        m_text(text)
{
}

Record::~Record()
{
}

namespace
{
const int RecordMetaTypeId = qMetaTypeId<Record>();
}

QML 片断:

Connections {
    target: listenPModel
    onGotRecord: {
        console.log(r)
        console.log(r.text)
    }
}

主要部分:

QGuiApplication app(argc, argv);

auto listenP = std::make_shared<ListenP>();
QQuickView view;
view.rootContext()->setContextProperty("listenPModel", &*listenP);
view.setSource(QStringLiteral("src/qml/main.qml"));
view.show();

QtConcurrent::run([=]
{
    QThread::sleep(3);
    listenP->emitGotRecord();
});

return app.exec();

日志显示:

qml: QVariant(Record)
qml: undefined

推荐答案

发行说明Qt 5.5 对新功能的说明:

The release notes for Qt 5.5 says for the new features:

  • Qt 核心
    • 您现在可以在 Q_GADGET 中包含 Q_PROPERTY 和 Q_INVOKABLE,并且可以使用 QMetaType 系统查询此类小工具的 QMetaObject
    • Qt Core
      • You can now have Q_PROPERTY and Q_INVOKABLE within a Q_GADGET, and there is a way to query the QMetaObject of such gadget using the QMetaType system

    确实,使用 Qt 5.4 编译和运行您的示例会得到与您的结果相同的结果 使用 Qt 5.5 我正确识别了 Record,即我得到的结果是:

    Indeed, compiling and running your example with Qt 5.4 gives the same result as yours whereas with Qt 5.5 I got Record correctly recognised, i.e. I got as a result:

    qml: Record(abc)
    qml: abc
    

    另外,如 Q_DECLARE_METATYPE 文档,传递给宏的类型 - 在这种情况下为 Record,应该提供 (1) 公共默认构造函数,(2) 公共复制构造函数和 (3) 公共析构函数.由于 Record 是一个非常简单的类,所以不需要提供复制构造函数,默认的就足够了.

    Also, as stated in the Q_DECLARE_METATYPE documentation, the type passed to the macro - Record in this case, should provide (1) a public default constructor, (2) a public copy constructor and (3) a public destructor. Since Record is a very simple class, there's no need to provide a copy constructor as the default one is sufficient.

    这篇关于将 Q_GADGET 作为信号参数从 C++ 传递到 QML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆