[SOLVED] Injecting Qml Objects created in c++ into existing Qml Elements
-
Hello, I created a C++ app with a QQuickView like this
QQuickView view; view.setSource(QUrl::fromLocalFile("MainItem.qml")); view.show();
MainItem.qml
import QtQuick 2.3 Item { width: 400 height: 400 Item { x: 0 y: 0 width: 300 height: 300 objectName: "subMainItem" ... } ... }
and I got my MainItem displayed
Then I load another Component from a Qml file
QQmlComponent component(&engine, QUrl::fromLocalFile("ChildItem.qml")); QObject *object = component.create();
ChildItem.qml
import QtQuick 2.3 Item { width: 100 height: 100 ... }
My question is now how can I inject the childItem into the MainItems subMainItem element? I already tried different variations with setting parent properties etc. but I don't get the child to become visible. Does somebody have a simple example? I'm working with Qt 5.4.1 and QtQuick 2.3
Thanks for your help
Edited: Use Markdown syntax rules - p3c0
-
Hi,
Did you "setParentItem":http://doc.qt.io/qt-5/qquickitem.html#parent-prop to ChildItem ?
-
Hello, thanks for the hint with the setParentItem method. But unfortunately it does not solve the problem
I'm still trying to figure out was going wrong. I did wrote a very simple program (going back to Qt 5.3.2) which opens a DeclarativeView from an Qml file with an Rectangle with red background inside - This red one is displayed in the view.
Then I create a QDeclarativeComponent from another Qml file which contains another Rectangle with yellow Background. I created an Object from it and call the setParentItem to connect it as a child to the root DeclarativeItem object (the red one).
Because my Qt is not compiled with debug option objectdump does not work for my and I wrote some own functions that prints out the parent/child tree including the attributes of the children. In the console output you can see that the yellow Item is a child of the red one and the attributes for x,y,z, width, height and visibility looking o.k.
But Item with the yellow Rectangle is not shown on the screen
I would be glad if there is somebody who can help me to solve the issue. I added the whole project if somebody want to try it. The project was build with Qt 5.3.2 on a Linux x86 32 bit environment.
PS: The code formating of the new forum it's a mess. The old format does not work anymore and the new one is some kind of random formating.
main.cpp
#include "mainwindow.h" #include <QApplication> #include <QtDeclarative> #include <QDeclarativeComponent> #include <QDeclarativeProperty> void printComponentErrors(QDeclarativeComponent* pComponent); quint32 printItemCildren(QDeclarativeItem* pParentItem, quint32 level); quint32 printItemAttributes(QDeclarativeItem* pItem, quint32 level); int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; QDeclarativeView* pView = new QDeclarativeView(); pView->resize(400,400); w.setCentralWidget(pView); QUrl myUrl("red.qml"); pView->setSource(myUrl); QDeclarativeView::Status viewerStatus = pView->status(); if (viewerStatus != QDeclarativeView::Ready ) { qDebug() << "Could not open qml file"; } else { bool success = false; QDeclarativeComponent component(pView->engine(),QUrl("yellow.qml")); QGraphicsObject* pRoot = pView->rootObject(); if (pRoot != NULL) { QObject* pObject = component.beginCreate(QDeclarativeEngine::contextForObject(pRoot)); QDeclarativeItem* pNewItem = qobject_cast<QDeclarativeItem*>(pObject ); if (pNewItem == NULL) { QDeclarativeComponent::Status status = component.status(); if ( status != QDeclarativeComponent::Ready ) { printComponentErrors(&component); } component.completeCreate(); } else { QDeclarativeItem* pRootItem = qobject_cast<QDeclarativeItem*>(pRoot); if (pRootItem != NULL) { pNewItem->setFlag(QGraphicsItem::ItemHasNoContents, false); pNewItem->setParentItem(pRootItem); QDeclarativeEngine::setObjectOwnership(pNewItem, QDeclarativeEngine::CppOwnership); success = QDeclarativeProperty::write(pNewItem, "objectName", "yellowBox"); success = QDeclarativeProperty::write(pNewItem, "visible", true); success = QDeclarativeProperty::write(pNewItem, "z", 20); pNewItem->deleteLater(); } component.completeCreate(); success = QDeclarativeProperty(pNewItem, "visible").write(false); success = QDeclarativeProperty(pNewItem, "visible").write(true); } QDeclarativeItem* pRootItem = qobject_cast<QDeclarativeItem*>(pRoot ); if (pRootItem != NULL) { printItemCildren(pRootItem, 1); } } } w.resize(400,400); w.show(); return a.exec(); } void printComponentErrors(QDeclarativeComponent* pComponent) { QList<QDeclarativeError> componentErrors = pComponent->errors(); quint16 errorNo = 1; QList<QDeclarativeError>::Iterator errorIter = componentErrors.begin(); while (errorIter != componentErrors.end()) { QDeclarativeError pQmlError = *errorIter; qDebug() << "QmlComponent error" << errorNo << ": " << pQmlError.toString(); errorIter++; } } quint32 printItemCildren(QDeclarativeItem* pParentItem, quint32 level) { QString levelString; quint32 itemsFound = 0; QString parentName = pParentItem->objectName(); QList<QGraphicsItem*> childItems = pParentItem->childItems(); QList<QGraphicsItem*>::Iterator childItemIter = childItems.begin(); for (quint32 i = 0; i< level; i++) { levelString = levelString + '+'; } printItemAttributes(pParentItem, level ); while (childItemIter != childItems.end()) { itemsFound ++; QDeclarativeItem* pChildItem = qobject_cast<QDeclarativeItem*>(*childItemIter); QString childName = pChildItem->objectName(); qDebug() << levelString << " " << parentName << " has child named " << childName; itemsFound += printItemCildren(pChildItem, level + 1); childItemIter++; } return itemsFound; } quint32 printItemAttributes(QDeclarativeItem* pItem, quint32 level) { quint32 attributesFound = 0; if (pItem != NULL) { QString levelString; QString itemName = pItem->objectName(); for (quint32 i = 0; i< level; i++) { levelString = levelString + '@'; } const QMetaObject *metaobject = pItem->metaObject(); int count = metaobject->propertyCount(); for (int i=0; i<count; ++i) { QMetaProperty metaproperty = metaobject->property(i); const char *name = metaproperty.name(); QVariant value = pItem->property(name); qDebug() << levelString << " " << itemName << " has property named " << name << " with value " << value; } } return attributesFound; }
mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; }
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
red.qml
import QtQuick 1.1 Rectangle { objectName: "redbox" width: 400 height: 400 color: "red" visible: true Text { text: "some text in red" anchors.centerIn: parent } }
yellow.qml
import QtQuick 1.1 Rectangle { objectName: "yellowBox" x: 0 y: 0 width: 20 height: 20 color: "yellow" visible: true Text { text: "some text in yellow" anchors.centerIn: parent } }
.pro file
#------------------------------------------------- # # Project created by QtCreator 2015-03-05T18:59:38 # #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets declarative TARGET = QmlTest TEMPLATE = app SOURCES += main.cpp\ mainwindow.cpp HEADERS += mainwindow.h FORMS += mainwindow.ui DISTFILES += \ red.qml \ yellow.qml
Edited: Use Markdown syntax rules - p3c0
-
Are you sure you are using Qt 5.3 ? QDeclarative* classes are a part of Qt4.x and have been deprecated in Qt5.
Have a look at this porting guide. -
Try the following example:
//MyItem.qml import QtQuick 2.4 Item { width: 200 height: 200 Rectangle { objectName: "subChildItem" width: 100 height: 100 color: "red" } } //main.cpp QQuickView view; view.setSource(QStringLiteral("qrc:/MyItem.qml")); view.show(); QQmlComponent component(view.engine()); component.setData("import QtQuick 2.0\nText { text: \"Hello\"; anchors.centerIn: parent }", QUrl()); QQuickItem *obj = qobject_cast<QQuickItem*>(component.create()); QQuickItem *item = view.rootObject()->findChild<QQuickItem *>("subChildItem"); obj->setParentItem(item);
Try commenting setParentItem to see the difference.
-
Thanks for your answer. I tried and it and it worked with QtQuick 2.3. When I comment the setParentItem method call the inserted text doesn't appear like expected.
But I can't use QtQuick >= 2 because the device for which I developing the application does not support OpenGL. That's the reason I'm using QtQuick 1.1. That's also the reason for using the Declarative instead the new Qml interface. Because the new QQml and QQuick interface seems to not supporting QtQuick 1.1.
So I'm forced from the target hardware to use QtQuick 1.1. Do you have any idea how to get it running with QQuick 1.1 and the Declarative interface?
-
Ok. Sorry, I'm not sure about the QDeclarative* stuff. Any errors printed in printComponentErrors ?
Also the new forum's editor follows markdown markup language and so it has its own syntax rules. For eg. to post code I have encapsulated it inside ` (backtick symbol). I have also edited your earlier posts.
Edit: Seems single backtick is enough too. -
Thanks for the code format hint and editing
Component creations were succesful .No, no component errors printed and the properties of the child and root Items printed by the attached functions looking o.k. for me but the child gots not displayed. Any other ideas?
-
pNewItem->deleteLater();
This could be the error. You are deleting the object as soon as you create them. -
Cool! If I remove the deleteLater it works :-) I did find an example somewhere in a forum thread and adopted the usage of deleteLater without knowing exactly what it does. In the thread they just say that it's neccessary to clean up all objects later. Know I read the docs and it makes sense what you say.
Thank you very much for your help. You saved my day