2017-02-16 16 views
2

У меня есть объект QML, который может создавать внутри него те же объекты. Функция addChildRect вызывается из C++. Каждый объект снабжен его уникальными id и objectName (для каждого объекта они одинаковы). Я хочу получить доступ к ним из C++, используя QObject::findChild, , но для динамически созданного объекта эта функция всегда возвращает нулевой указатель. Мое предложение состоит в том, что эта функция анализирует только объекты, которые были в QML изначально. Как получить доступ к динамически созданным объектам из C++?Доступ к динамически созданным объектам QML из C++

Rect.qml

Rectangle { 
    color: "red" 
    function addChildRect(id,x,y,width,height) 
    { 
     var component; 
     component = Qt.createComponent("Rect.qml"); 
     component.createObject(this, { 
           id:id, 
           objectName:id, 
           x:x, 
           y:y, 
           width:width, 
           height:height}); 
    } 
} 

C++ код:

//find element 
auto parentRectView = engine.rootObjects().first()->findChild<QObject*>(QString::number(id())); 


//create element 
QMetaObject::invokeMethod(parentRectView,"addChildRect", 
          Q_ARG(QVariant,id()), 
          Q_ARG(QVariant,m_position.x()), 
          Q_ARG(QVariant,m_position.y()), 
          Q_ARG(QVariant,m_size.height()), 
          Q_ARG(QVariant,m_size.width())); 
+2

Я думаю, вы должны установить родительский объект для динамически создаваемых объектов, чтобы найти с помощью 'QObject :: findChild'. Кроме того, чтобы избежать ненужных действий, вы можете просто вернуть указатель на созданный объект из 'addChildRect' в C++ – folibis

+0

@folibis спасибо за ваш ответ? правильно ли я вас понял, что я должен добавить «parent: this» в код построения объекта QML? Также не могли бы вы предоставить мне простой пример, как вернуть указатель из QML? – Lecko

+0

См. Мой ответ ниже – folibis

ответ

2

Предположим, что мы следующий код QML (main.qml):

Window { 
    width: 300 
    height: 400 
    visible: true 
    id: window 

    Component { 
     id: testItem 
     Rectangle { 
      width: 100 
      height: 100 
      color: "green" 
      anchors.centerIn: parent 
     } 
    } 

    function addItem(name) 
    { 
     var component = testItem.createObject(window.contentItem, {objectName: name}); 
     return component; 
    } 
} 

Обратите внимание - как родитель, я прохожу Item, в моем случае это Window.contentItem - скрытый корневой элемент Window, так как Окно не Item. Я не javascript-гуру, но я думаю, что this вы используете здесь указатель на функцию, а не на Item.

Хорошо, а вот C++ код:

QQmlApplicationEngine engine; 
engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 
QObject *item = dynamic_cast<QObject *>(engine.rootObjects().at(0)); 
QVariant retVal; 
QMetaObject::invokeMethod(item, "addItem", Qt::DirectConnection, 
          Q_RETURN_ARG(QVariant, retVal), 
          Q_ARG(QVariant, "test")); 

qWarning() << retVal; 

В моем случае на выходе будет что-то вроде

QVariant (QObject *, QQuickRectangle (0x2c125490, имя = "тест"))

Вам просто нужно бросить QVariant к QQuickItem или QObject.

Что касается поиска динамически созданных объектов, вы правы. Например, выход следующего кода:

QObject *rect = qvariant_cast<QObject*>(retVal); 
qWarning() << rect; 
QObject *myitem = item->findChild<QObject *>("test"); 
qWarning() << myitem; 

будет:

QQuickRectangle(0x2c270d38, name = "test") 
QObject(0x0) 

findChild возвращает нуль, хотя parent из rect установлен. Возможно, кто-то может объяснить это странное поведение.

+0

Спасибо! Я понял! – Lecko

+0

Используйте 'qobject_cast' для' QObject' и полученные, лучше в нескольких аспектах, включая производительность. – dtech

+0

@folibis 'parent' в QML является« parentItem », как в' QQuickItem :: parentItem() ', который не обязательно совпадает с родителем QObject, как в' QObject :: parent() ' –