1

(Editted to add more context)

I've started using QML and I'd like to set some sort of reference property on a QML type, linking two QML objects (ideally, without a parent/child relationship as I'd like to connect multiple QML objects).

For example, I have the following files.

qmldir:

A 1.0 A.qml

A.qml

import QtQuick 2.2

Rectangle {
    width: 100
    height: 100
    color: 'red'
    // Other stuff later
}

main.qml:

import QtQuick 2.2
import QtQuick.Window 2.1
import "qrc:/"

Rectangle {
    objectName: "Main window"
    visible: true
    width: 360
    height: 360

    MouseArea {
        anchors.fill: parent
        onClicked: {
            Qt.quit();
        }
    }

    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }

    property A referencedObject;

    Rectangle {
        id: subView
        objectName: "subView"
    }
}

What I'd like to do with this is set the value of 'referencedObject' to an object created by C++ at runtime. However, the function for setting properties doesn't allow for QObject pointers or QQuickItem pointers, as QVariant objects can't be constructed that way.

Something like:

QQmlComponent aTemplate(&engine, QString("qrc:/A.qml"), &parentObject);
QQuickItem* aInstance = aTemplate.create();

aInstance->setParent(&parentObject);
mainView.setProperty("referencedObject",aInstance); // Won't work.

I'd like to keep the 'A' type object in QML because a) less boilerplate than C++ for this, and b) its meant to be a separate graphical object with life of its own, and QML works better for that use-case.

Thanks for any help posted.

Doug
  • 775
  • 2
  • 11
  • 24

1 Answers1

2

The following example shows how to set properties of objects of your custom type defined in QML from C++.

A.qml

import QtQuick 2.2
Rectangle {
    width: 0
    height: 0
    color:"red"
}

main.qml

import QtQuick 2.2  
Rectangle {
    visible: true
    width: 640
    height: 480

    property alias referencedObject:aProperty;

    A
    {
        id:aProperty
        objectName: "aPropertyObject"//Needed to access it from C++
    }
}

Now we have defined a qml type A. main.qml has a property of this Custom type. We need to change properties of this object from C++. Lets change the width,height and color.

main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QQuickItem>
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    QQmlComponent aTemplate(&engine, QUrl(("qrc:///A.qml")));
    QQuickItem* aInstance =qobject_cast<QQuickItem*>(aTemplate.create());
    aInstance->setWidth(100);
    aInstance->setHeight(100);
    aInstance->setProperty("color",QColor("green"));
    if(aInstance)
    {
        QQuickView *mainView = new QQuickView;
        mainView->setSource(QUrl(QStringLiteral("qrc:///main.qml")));
        mainView->show();
        QQuickItem * aPropertyObject = mainView->rootObject()->findChild<QQuickItem*>("aPropertyObject");
        if(aPropertyObject)
        {
           //Now you have pointers to both source and destination.
           //You can write a helper function which assigns the values
           //of source to the destination.
           //For the sake of demonstration, I am just setting some properties.       
           aPropertyObject->setWidth(aInstance->width());
           aPropertyObject->setHeight(aInstance->height());
           aPropertyObject->setProperty("color",aInstance->property("color"));
        }
    }
    return app.exec();
}
Programmer
  • 1,290
  • 2
  • 12
  • 16
  • Not really what I'm after - I've added more information to my original post, but mainly, I'd like the 'MyCustomType' to be a QML based object as its meant to be a graphical front. Is it possible to link them more directly, or is C++ required to make this level of logical linking possible? – Doug Sep 01 '14 at 19:40
  • I have edited my answer. I hope your problem gets solved with this answer. – Programmer Sep 02 '14 at 13:13
  • Thanks for the edit. This about does what I want - I think QML does lack the more direct method that would be ideal, but this does the job nicely. – Doug Sep 02 '14 at 15:14
  • Accessing and manipulating QML objects from C++ is possible but it is not recommended for use in your production code. For more details please see this [warning](http://qt-project.org/doc/qt-5/qtqml-cppintegration-interactqmlfromcpp.html#accessing-loaded-qml-objects-by-object-name) in qt docs(See Warning marked in bold in docs). There are better ways to interact with QML and C++. In your case, whenever you want to change the property of your custom type, you can emit a signal with the new value to be set. On QML side you can listen to this signal and change the property on receiving signal. – Programmer Sep 02 '14 at 15:35
  • Thanks for your advice - after alittle more practice with QML, I have begun incorporating it in. – Doug Sep 04 '14 at 19:38