将 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. SinceRecord
is a very simple class, there's no need to provide a copy constructor as the default one is sufficient.
相关文章