Подтвердить что ты не робот

Как получить доступ к вложенному объекту QML из С++?

Вот пример воспроизводимости:

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();
}

Я хочу получить доступ к property somenumber text QML Item. Вышеуказанный метод не дает желаемого результата.

Как это сделать?

4b9b3361

Ответ 1

У вас есть два способа (по крайней мере) выполнить это в зависимости от ваших личных предпочтений.

Расширение кода QML

Вы можете добавить псевдоним свойства к корневому элементу следующим образом:

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();
        }
    }
}

Расширение кода С++

Поскольку элементы QML QObject, вы также можете явно искать дочерние элементы, как и в иерархии С++ QObject. Код будет примерно таким:

#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();
}

Однако это означает, что вам нужно будет добавить строку objectName: "SomeNumberText" в свой текстовый элемент Text в файле qml.

Ответ 2

Здесь вы можете найти рекурсивный метод для поиска элемента QML с помощью objectName и начиная с 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);
}

Ответ 3

Каков прецедент для этого? Возможно, было бы лучше просто обработать структуру или объект [text, someNumber] в качестве модели. Тогда вам нужно всего лишь найти объект модели. Или вы можете создать объект модели на стороне С++ и установить его в контексте QML. Вы можете получить доступ к модели и ее вложенным свойствам в QML:

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