Mixed QML/C++ app (solved)



  • Hi,
    I have created a mixed QML/C++ app, and I would like to be able to create a QML type object and add it to my main.qml as a child, from my main.cpp.

    I have created it by using :
    QQmlComponent component(&engine, "C:/....", QQmlComponent:PreferSynchronous);
    QObject *object = component.create();
    But now I would like to be able to specify that its parent should be my main.qml.

    Any idea ?

    Thanks !



  • I forgot to say that I also wrote :
    QQmlEngine::setObjectOwnerShip(object, QQmlEngine::CppOwnerShip);
    object -> setParent(&engine);


  • Moderators

    Hi @LaurianeLt,

    I forgot to say that I also wrote :
    QQmlEngine::setObjectOwnerShip(object, QQmlEngine::CppOwnerShip);
    object -> setParent(&engine);

    That code sets the object parent, but you need to set the visual parent. See the differences here: http://doc.qt.io/qt-5/qtquick-visualcanvas-visualparent.html

    To set the visual parent, use QQuickItem::setParentItem(). (you need to typecast object to QQuickItem first)



  • Hi @JKSH ,
    Thank you for your answer, I will try that and let you know how it worked !



  • I did as you said but I still have some problems, here is what I wrote :

    QQmlApplicationEngine engine;
    ...
    QQmlComponent component (&engine, "C:/Qt/.../Rectangle.qml", QQmlComponent:PreferSynchronous);
    QQuickItem * object = qobject_cast<QQuickItem*>(component.create());

    QQmlComponent component1 (&engine, "C:/Qt/.../main.qml", QQmlComponent:PreferSynchronous);
    QQuickItem * parent = qobject_cast<QQuickItem*>(component1.create());

    object->setParent(&engine);
    object->setParentItem(parent);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml)));

    First I know that the way I create the "parent", when I run it, it opens two windows, the "main.qml" is launched twice. I would like to be able to define my "engine" as the parent but it's not a QQuickItem..

    And even like this, my qml object "rectangle.qml" does not appear in the window when I run it.



  • So I tried to define the visual parent this way :

    QQuickItem root = qobject_cast<QQuickItem>(engine.rootObjects().first());
    object->setParentItem(root);

    It's running fine but once again, the rectangle.qml is not displayed...

    Any idea ?


  • Moderators

    Hi,

    Please add three backticks (```) before and after your code to make it render nicely.

    @LaurianeLt said:

    it opens two windows, the "main.qml" is launched twice.

    That's because you created the "main.qml" component twice:

    QQmlComponent component (&engine, "C:/Qt/.../Rectangle.qml", QQmlComponent:PreferSynchronous);
    QQuickItem * object = qobject_cast<QQuickItem*>(component.create()); // <-- First creation
    ...
    engine.load(QUrl(QStringLiteral("qrc:/main.qml))); // <-- Second creation
    

    I would like to be able to define my "engine" as the parent but it's not a QQuickItem.

    Why do you want to set "engine" as the parent?

    An item is painted "inside" its visual parent. An engine cannot be painted seen, so it cannot be a visual parent.

    And even like this, my qml object "rectangle.qml" does not appear in the window when I run it.

    I just realized that you are using QQmlEngine, which means that the root type inside main.qml is probably a Window, is that correct? If so, note that Window does not inherit Item, so it is not a QQuickItem either. Look for the QQuickItems inside the Window by calling engine.rootObjects().first()->children().

    I suggest you check the application output on the console. They provide many hints to help you solve your problems. You can print your own messages using qDebug():

    qDebug() << engine.rootObjects();
    


  • Hi @JKSH,

    Thank you so much for your answer and the tip.

    I realised I was creating it twice but I wanted to see if I was able this way to make my "main.qml" be the parent of "rectangle.qml".

    I realize that what I said was not clear at all. I don't want to set "engine" as the parent, but my "main.qml" which is the qml file I load with the engine.

    I am using QQmlEngine indeed so my main.cpp in its simplest form is this :

    int main( int argc, char *argv[])
    {
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
    }
    
    

    So what I want to be able to do is to create and declare an object "rectangle.qml" a child of "main.qml" from my "main.cpp".

    I hope I am making more sense now, I will try to figure more out by looking at the children of engine.rootObjects().first().

    Thanks again!



  • @JKSH I forgot : the root type inside main.qml is an ApplicationWindow.



  • I tried this :

    qDebug << engine.rootObjects().first()->children();
    

    And I get something like this, with the list of the children :
    (QQuickLoader(0x26c5ff98, QQuickItem(0x26c5fcf8), ... )

    So I tried to get the second one, which is a QQuickItem like that :

    QQuickItem parent = qobject_cast<QQuickItem*>(engine.rootObjects().first()->children().at(2));
    

    But I get a error message saying that "QQuickItem::QQuickItem(const QQuickItem&)' is private" .


  • Moderators

    @LaurianeLt said:

    @JKSH I forgot : the root type inside main.qml is an ApplicationWindow.

    Yep, that inherits Window. It's not a QQuickItem.

    QQuickItem parent = qobject_cast<QQuickItem*>(engine.rootObjects().first()->children().at(2));
    

    But I get a error message saying that "QQuickItem::QQuickItem(const QQuickItem&)' is private" .

    You got that error message because the type of parent needs to be QQuickItem*, not QQuickItem.

    Also note that counting starts from 0, so if you want the second item you should call .at(1).



  • @JKSH Thank you so much, this is finally working !


  • Moderators

    @LaurianeLt You're welcome :) Happy coding!


Log in to reply
 

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