[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


  • Moderators

    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


  • Moderators

    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.


  • Moderators

    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?


  • Moderators

    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?


  • Moderators

    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


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.