qt — Взаимодействие с делегированным компонентом QML в повторителе из переполнения стека

Я не могу получить доступ к делегированному компоненту QML в Repeater из C ++. Пожалуйста, найдите коды ниже. Благодарю.

main.cpp

#include <QApplication>
#include <QDebug>
#include <QQuickView>
#include <QQuickItem>

int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/Main.qml")));
view.show();
QQuickItem *object = view.rootObject();
QObject *rectangle = object->findChild<QObject*>("rect1");

if (!rectangle)
qDebug() << "MyError: rectangle was not found";

app.exec();
}

Main.qml

import QtQuick 2.4

Row {
Repeater {
model: 3
Rectangle {
width: 50; height: 50
color: index %2 ? "black" : "white"objectName: "rect" + index
}
}
}

Консольный вывод:

MyError: rectangle was not found

2

Решение

Я реализовал собственную рекурсивную функцию шаблона ‘findChild’ в C ++. `

template <class T>
SearchType findChild(QQuickItem* object, const QString& objectName)
{
QList<QQuickItem*> children = object->childItems();
foreach (QQuickItem* item, children)
{
if (QQmlProperty::read(item, "objectName").toString() == objectName)
return item;

T child = findChild<QQuickItem*>(item, objectName);

if (child)
return child;
}
return nullptr;
}

И вместо этого назовите его функцией по умолчанию.

QQuickItem *object = view.rootObject();
QQuickItem *rectangle = findChild<QQuickItem*>(object, "rect1");

if (rectangle)
{
qDebug() << rectangle;
qDebug() << rectangle->objectName();
}

И получить вывод:

QQuickRectangle(0x2222b40, name="rect1", parent=0x22245b0, geometry=50,0 50x50)
"rect1"
3

Другие решения

Если вы вызываете object->dumpObjectTree() вы увидите что-то вроде следующего вывода консоли:

QQuickRow::
QQuickRepeater::
QQmlComponent::

Как видите, дерево объектов не содержит прямоугольников в качестве выделенных объектов. В моем ограниченном понимании на стороне QML есть другое дерево, содержащее все видимые элементы / компоненты qml. К ним вы можете получить доступ по крайней мере через свойство children из qml. Чтобы показать это, я изменил ваш qml-файл на:

Main.qml:

Row {
id: row
Repeater {
model: 3
Rectangle {
width: 50; height: 50
color: index %2 ? "black" : "white"objectName: "rect" + index
}

}
Component.onCompleted: {
console.log(row.children[0].objectName);
console.log(row.children[1].objectName);
console.log(row.children[2].objectName);
}

}

С полученным следующим выводом:

qml: rect0
qml: rect1
qml: rect2
MyError: rectangle was not found

Конечно, прямая доступность и индекс зависят от ваших дополнительных элементов / компонентов. С этого момента вы можете написать свою собственную рекурсивную функцию ‘findChild’ и представить объекты результата в C ++. Здесь описано, как: http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html

Например, вы можете реализовать ‘findChild’ в qml следующим образом:

function findChild(propertyName, propertyValue) {
return findChildRecursivly(row, propertyName, propertyValue)
}

Эта функция qml, которую вы можете вызвать из C ++, например

QVariant result;
QMetaObject::invokeMethod(object, "findChild",
Q_RETURN_ARG(QVariant, result),
Q_ARG(QVariant, "objectName"),
Q_ARG(QVariant, "rect1"));
rectangle = result.value<QObject *>();

Со следующими дополнительными строками кода:

if (!rectangle)
{
qDebug() << "MyError: rectangle was not found";
}
else
{
qDebug() << rectangle;
qDebug() << rectangle->objectName();
}

вы получите следующий вывод:

QQuickRectangle(0x1c1beef, name = "rect1")
"rect1"
0

По вопросам рекламы [email protected]