Перечислить все объекты в QQmlEngine

Я хочу перечислить все объекты (производные от QObject), существующие и вновь созданные в QQmlApplicationEngine. Основная цель — выполнить следующие строки кода для каждой из них:

void denominate(QObject * const object)
{
    if (object->objectName().isEmpty()) {
        object->setObjectName(object->metaObject()->className());
    }
}

Это необходимо, чтобы различать некоторые объекты в среде выполнения QML. Скажем, когда из Component создается StackView элементов, и я хочу знать, какой из них действительно находится сверху.

Создание некоторых компонентов или классов C++ задерживается. И если я получу корневые объекты и перечислю их children(), это половина решения. Также есть сигнал QQmlApplicationEngine::objectCreated, но я не до конца понимаю взаимосвязь между контекстами, движком и (корневыми) объектами.

Как назвать все безымянные объекты, которые живут в QQmlEngine?


person Tomilov Anatoliy    schedule 22.08.2017    source источник
comment
Обратите внимание, что typeof всегда возвращает объект.   -  person Tomilov Anatoliy    schedule 22.08.2017
comment
Вы можете вызвать пользовательский сигнал из QML в методе Component.OnCompleted и отправить QObject в качестве параметра.   -  person arturx64    schedule 22.08.2017
comment
@arturx64 Для всех объектов? Нет. Конечно, могу, но не хочу. В Qt (и QML) есть дерево объектов, и я просто хочу его пройти.   -  person Tomilov Anatoliy    schedule 22.08.2017
comment
@ arturx64 Есть еще более простой способ: установить свойство objectName только для интересных объектов. Но это также подверженный ошибкам подход. Что, если я пропущу инициализацию этого свойства для некоторых интересующих объектов?   -  person Tomilov Anatoliy    schedule 22.08.2017
comment
Вы должны работать только с появившимся объектом. Теоретически вам нужно свойство visible элемента QML. Попробуйте подключиться к OnVisibleChanged, сигналу или другому сигналу, пока вы перечисляете все объекты.   -  person arturx64    schedule 22.08.2017
comment
@ arturx64 Но вопрос в том, как перечислить. Я не могу понять ваши предложения.   -  person Tomilov Anatoliy    schedule 22.08.2017
comment
Попробуйте перечислить все объекты в QML, используя метод childItems QQuickItem. forum.qt.io/ тема/43334/   -  person arturx64    schedule 22.08.2017
comment
@arturx64 У меня никого нет QQuickItem. Связанный код не является C++.   -  person Tomilov Anatoliy    schedule 22.08.2017
comment
Это базовый класс для всех визуальных компонентов. Когда вы создаете элемент QML со стороны c++, указатель QQuickItem* используется следующим образом: QQmlComponent component(m_qmlEngine, QUrl(qmlPath)); QQuickItem* item = qobject_cast‹QQuickItem*›(omponent.create());   -  person arturx64    schedule 22.08.2017


Ответы (1)


Вы можете переименовать их все, используя рекурсивное перечисление. Например: файл QML:

import QtQuick 2.6
import QtQuick.Window 2.2

Window {
   visible: true
   width: 640
   height: 480
   title: qsTr("Hello World")

MouseArea
{
    id: r1
    width: 200
    height: 200
}

Rectangle
{
    id: r2
    color: "green"
    width: 100
    height: 100
    Item
    {
        id: r3
        width: 50
        height: 50
    }
}
}

Вы можете установить их имена в части c++, используя следующий механизм:

 void changeNames(QList<QObject*> ch)
 {
    for( QObject* ob: ch)
    {
        if (ob->objectName().isEmpty())
        {
            ob->setObjectName(ob->metaObject()->className());
        }
        changeNames( ob->children() );
    }
}

void enumerate(QList<QObject*> ch)
{
    for( QObject* ob: ch)
    {
        qInfo() << ob->objectName();
        enumerate( ob->children() );
    }
}

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

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    QObject *rootObject = engine.rootObjects().first();

    changeNames(rootObject->children());
    enumerate(rootObject->children());

    return app.exec();
}

В выводе вы увидите следующие имена:
"QQuickRectangle"
"QQuickMouseArea"
"QQuickItem"

Если вам нужно добавить новый компонент динамически, вы можете повторить эту процедуру или найти нужный компонент и переименовать его.

person arturx64    schedule 22.08.2017
comment
Что, если не я? Как уловить все события? - person Tomilov Anatoliy; 22.08.2017
comment
Если вы хотите перехватывать все события, вы можете использовать фильтр событий doc.qt.io/qt- 4.8/eventsandfilters.html - person arturx64; 22.08.2017