QML: Type Error with custom QObject
It helps if you break down the expression on the line where the error is coming from. Try just printing myData.a
first:
print(myData.a)
myData.a = mouse.x;
myData.b = mouse.y;
qrc:///main.qml:31: TypeError: Cannot read property 'a' of null
So, myData
is null
. We can verify this with another QObject
-based type:
MouseArea {
property DataObject myData;
property Item item
anchors.fill: parent
drag.target: parent
onReleased: {
print(item)
myData.a = mouse.x;
myData.b = mouse.y;
}
}
qml: null
So, you can fix this error by initialising the property:
property DataObject myData: DataObject {}
You can think of QObject-based properties as pointers for JavaScript; they can be null
or point to a valid object... or be undefined
. :) I can't find anything mentioned about this here, but that's where this behaviour should be mentioned.
If you'd like to simplify things, you can have the object default-constructed for you by making it a child object of the MouseArea
, rather than a property:
MouseArea {
DataObject {
id: myData
}
anchors.fill: parent
drag.target: parent
onReleased: {
myData.a = mouse.x;
myData.b = mouse.y;
}
}
Currently, you won't be able to refer to this property from C++. However, you can achieve this in two ways:
- Declare a property alias to the item.
- Give it an
objectName
and use QObject::findChild to find it.
Doug
Updated on July 02, 2022Comments
-
Doug almost 2 years
I'm trying out something in QML to try and make it alittle easier to merge the two more seamlessly; to be precise, I'm trying to link an object with structured data to QML.
I have the following setup:
main.cpp:
#include <QApplication> #include <QQmlApplicationEngine> #include <QtQml> #include "dataobject.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); qmlRegisterType<DataObject>("DO", 1,0,"DataObject"); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:///main.qml"))); return app.exec(); }
dataobject.h:
#ifndef DATAOBJECT_H #define DATAOBJECT_H #include <QObject> #include <QVariant> #include <iostream> class DataObject : public QObject { Q_OBJECT Q_PROPERTY(qreal a MEMBER a NOTIFY aChanged) Q_PROPERTY(qreal b MEMBER b NOTIFY bChanged) public: explicit DataObject(QObject *parent = 0); signals: void aChanged(); void bChanged(); public slots: void printState() { using namespace std; cout << a << ", " << b << endl; } private: qreal a; qreal b; }; #endif // DATAOBJECT_H
dataobject.cpp:
#include "dataobject.h" DataObject::DataObject(QObject *parent) : QObject(parent) { connect(this, SIGNAL(aChanged()), this, SLOT(printState())); connect(this, SIGNAL(bChanged()), this, SLOT(printState())); }
main.qml:
import DO 1.0 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") menuBar: MenuBar { Menu { title: qsTr("File") MenuItem { text: qsTr("Exit") onTriggered: Qt.quit(); } } } Text { text: qsTr("Hello World") MouseArea { property DataObject myData; anchors.fill: parent drag.target: parent onReleased: { myData.a = mouse.x; myData.b = mouse.y; } } } }
qml.qrc:
<RCC> <qresource prefix="/"> <file>main.qml</file> </qresource> </RCC>
Now, what I'd hoped was that values generated by QML could be feed into a object in C++ directly (i.e. the onReleased handler in the MouseArea trying to write to the myData field). However, this basic proof of concept doesn't work, but I don't really understand why.
The error I get (on drag and release of the mouse button) is: qrc:///main.qml:29:TypeError:Type error
Which matches up with the line "myData.a = mouse.x;", so it fails straight away.
Any idea's where I'm going wrong? I've tried with the fields being int, double, QVariant, and qreal, none of which have worked. Is in a fundamental inability in QML to link objects like that? If so, any idea how, for example, anchors.fill is implemented in the Qt source code?