QML: type error with custom QObject

I'm trying to do something in QML to try and make it easier to merge the two more smoothly; to be precise, I am trying to link a structured data object with 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 I was hoping that the values ​​generated by QML could be directly cast to a C ++ object (i.e. the onReleased handler in MouseArea is trying to write to the myData field). However, this basic proof of concept doesn't work, but I really don't understand why.

The error I am getting (while dragging and releasing the mouse button) is: qrc: ///main.qml: 29: TypeError: Please enter an error

Which matches the line "myData.a = mouse.x;" so it will fire immediately.

Any idea where I am going wrong? I've tried using int, double, QVariant and qreal fields, none of which worked. Is there a fundamental inability in QML to bind such objects? If so, any idea how, for example, anchors.fill is implemented in the Qt source code?

+3


source to share


1 answer


It helps if you break the expression on the line where the error is coming from. Try to print first myData.a

:

print(myData.a)
myData.a = mouse.x;
myData.b = mouse.y;

      

qrc: ///main.qml: 31: TypeError: Cannot read property 'a' from null

So myData

- null

. We can check this with another type QObject

:

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 initializing the property:



property DataObject myData: DataObject {}

      

You can think of QObject-based properties as JavaScript pointers; they can either be null

pointing to a valid object ... or be undefined

. :) I can't find anything mentioned about this here , but in this case, this behavior should be mentioned.

If you want to simplify things, you can create a default object created for you by making it a child object MouseArea

, not a property:

MouseArea {
    DataObject {
        id: myData
    }
    anchors.fill: parent
    drag.target: parent

    onReleased: {
        myData.a = mouse.x;
        myData.b = mouse.y;
    }
}

      

You will not be able to reference this property from C ++ at this time. However, you can achieve this in two ways:

+6


source







All Articles