I have a Q_GADGET MyGadget
defined in a file mygadget.h
#include <QObject>
class MyGadget {
Q_GADGET
Q_PROPERTY(int value READ value CONSTANT)
public:
MyGadget() = default;
MyGadget(int i)
: _value{i}
{
}
int value() const
{
return _value;
}
private:
int _value{0};
};
Q_DECLARE_METATYPE(MyGadget)
Q_DECLARE_METATYPE(MyGadget*)
and a Context
class that holds an instance of MyGadget
and exposes a pointer to it to QML via a Q_PROPERTY:
#include <QObject>
#include "mygadget.h"
class Context : public QObject
{
Q_OBJECT
Q_PROPERTY(MyGadget* gadget READ gadget CONSTANT)
public:
explicit Context()
: QObject{nullptr}
{
}
MyGadget* gadget() {
return &_gadget;
}
private:
MyGadget _gadget{4};
};
An instance of Context
is created in main
and exposed to QML as a context property:
#include <QGuiApplication>
#include <QQuickView>
#include <QString>
#include <QQmlContext>
#include "context.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view;
Context c;
// register MyGadget
qmlRegisterUncreatableType<MyGadget>("Test", 1, 0, "MyGadget", "");
qRegisterMetaType<MyGadget*>(); // <- removing this doesn't change anything
// make Context instance a context propery
view.rootContext()->setContextProperty("context", &c);
// show QML
view.setSource(QUrl{QStringLiteral("qrc:/main.qml")});
view.show();
return app.exec();
}
The QML file used with this is
import QtQuick 2.5
import Test 1.0
Rectangle {
height: 600
width: 800
visible: true
Text {
text: qsTr("Hello World " + context.gadget.value)
anchors.centerIn: parent
}
}
Everything compiles fine, but when running it no text isn't shown and QML emits a warning
qrc:/main.qml:9: TypeError: Cannot read property 'value' of null.
If I remove the call to qmlRegisterUncreatableType<MyGadget>
in main
and the corresponding import Test 1.0
in the QML file, the text "Hello World undefined" is shown instead.
The only way I got it to print "Hello World 4" as expected is to have Context::gadget
return a copy of the stored MyGadget
object instead of a pointer to it, or to make MyGadget
a Q_OBECT
instead. But both of these are not viable options in my real application, since I need reference semantics here, but in other places I'd also like to have value semantics for the class corresponding to MyGadget
in this example.
How can I get QML to read the correct property value?