14

Here is a reproducible example:

main.qml


import QtQuick 2.0

Item {
    id : root
    width: 360
    height: 360

    Text {
        id : t1
        text: qsTr("Hello World")
        property int someNumber: 1000
        anchors.centerIn: parent
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            Qt.quit();
        }
    }
}

main.cpp


#include <QtGui/QGuiApplication>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QQmlProperty>
#include <QDebug>

#include "qtquick2applicationviewer.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/untitled/main.qml"));
    viewer.showExpanded();

    QQmlEngine engine;
    QQmlComponent component(&engine, "qml/untitled/main.qml");
    QObject *object = component.create();

    qDebug() << "Property value:" << QQmlProperty::read(object, "root.t1.someNumber").toInt();

    return app.exec();
}

I wish to access the property somenumber of the text of the QML Item. The above method isn't producing the desired result.

How to do it?

5
  • 1
    Why not property alias? Commented Dec 27, 2013 at 12:38
  • @LaszloPapp didn't understand, please explain. Commented Dec 27, 2013 at 12:38
  • 1
    property alias mytext: t1.text for the root item, or 'QObject *object = object->findChild<QObject*>("t1");` Commented Dec 27, 2013 at 12:39
  • In QML you title the Text "t1" but in C++ you access it as "ti". Typo? Commented Aug 29, 2016 at 17:30
  • @StefanMonov that may be typo. Thanks for pointing out. Commented Aug 30, 2016 at 4:36

3 Answers 3

11

You have two ways (at least) to accomplish this depending on your personal preference.

QML code extension

You can add a property alias to the root item as follows:

import QtQuick 2.0

Item {
    id : root
    width: 360
    height: 360

    property alias mySomeNumber: t1.someNumber // This is the addition

    Text {
        id : t1
        text: qsTr("Hello World")
        property int someNumber: 1000
        anchors.centerIn: parent
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            Qt.quit();
        }
    }
}

C++ code extension

Since the QML items are QObject, you can look for the children explicitly as well, just as you would do it in a C++ QObject hierarchy. The code would be something like this:

#include <QtGui/QGuiApplication>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QQmlProperty>
#include <QDebug>

#include "qtquick2applicationviewer.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/untitled/main.qml"));
    viewer.showExpanded();

    QQmlEngine engine;
    QQmlComponent component(&engine, "qml/untitled/main.qml");
    QObject *object = component.create();

    // This line is added

    QObject *childObject = object->findChild<QObject*>("SomeNumberText");

    // The following line is modified respectively

    qDebug() << "Property value:" << QQmlProperty::read(childObject, "someNumber").toInt();

    return app.exec();
}

However, this means you will need to add the objectName: "SomeNumberText" line to your Text child item in the qml file.

Sign up to request clarification or add additional context in comments.

6 Comments

findChild searches for an object with the given objectName property value, which is not equal to QML's id. If we assume that the QML code should not be modified, that's not a solution. Otherwise, we have to add objectName: "tr1" in QML.
@leemes: you are right and too fast. I was busy with adding lotta more code and fixing bugs in the initial version. ;-)
Do you know any way to find a QML item by using its id? This would allow us to find items without adding an objectName.
@pedromateo: as far as I know "id" is a qml property usually, so naturally, that would not work for all QObjects. Now, it might be possible that some QML C++ class will have some qml specific children finder algorithm, but I am not sure if it is common enough a use case.
@Ipapp: you are right. I read that id does exist only in QML layer, and not at QObject level.
|
2

Here you can find a recursive method looking for a QML item by objectName and starting at QQmlApplicationEngine::rootObjects():

////
static QQuickItem* FindItemByName(QList<QObject*> nodes, const QString& name)
{
    for(int i = 0; i < nodes.size(); i++){
        // search for node
        if (nodes.at(i) && nodes.at(i)->objectName() == name){
            return dynamic_cast<QQuickItem*>(nodes.at(i));
        }
        // search in children
        else if (nodes.at(i) && nodes.at(i)->children().size() > 0){
            QQuickItem* item = FindItemByName(nodes.at(i)->children(), name);
            if (item)
                return item;
        }
    }
    // not found
    return NULL;
}

///
static QQuickItem* FindItemByName(QQmlApplicationEngine* engine, const QString& name)
{
    return FindItemByName(engine->rootObjects(), name);
}

2 Comments

Why not just call QObject::findChild for each item in QQmlApplicationEngine::rootObjects()? It's recursive by default. Seems like you're reinventing the wheel.
No, it's not. In fact, the very reason of it not being recursive is what brought me here.
0

What is the use case for this? It might be better to just treat the [text, someNumber] struct or object as the model. Then you only need to find the model object. Or you could create the model object on the C++ side and set it in the QML context. You could access the model and its nested properties in QML:

Text {
        text: model.text
        property int someNumber: model.someNumber
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.