将Q_GADGET作为信号参数从c++传递到QML

Passing Q_GADGET as signal parameter from C++ to QML

本文关键字:c++ QML 参数 信号 GADGET      更新时间:2023-10-16

不能在QML代码中获得c++对象的属性。对象作为参数传递给信号。

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

RecordQPoint一样是值类型,所以它使用Q_GADGET声明。

高压泵:

#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 for Record:

#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 for Record

#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的发布说明中提到了新特性:

  • Qt核心
    • 现在可以在Q_GADGET中拥有Q_PROPERTY和Q_INVOKABLE,并且有一种方法可以使用QMetaType系统
    • 查询此类gadget的QMetaObject

事实上,用Qt 5.4编译和运行您的示例与您的给出相同的结果,而与Qt 5.5我得到了Record正确识别,即我得到了结果:

qml: Record(abc)
qml: abc

同样,正如Q_DECLARE_METATYPE文档中所述,传递给宏的类型(本例中为Record)应该提供(1)一个公共默认构造函数,(2)一个公共复制构造函数和(3)一个公共析构函数。由于Record是一个非常简单的类,因此不需要提供复制构造函数,因为默认构造函数已足够。