Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Calling JS functions in loaded components from C++



  • Hi
    i have main.qml file that it have one JS function in it, i can call the function from C++ by "Q_INVOKABLE" and "QMetaObject::invokeMethod", also i have another Qml file "MyFile.qml" that loaded into "main.qml" with this code:

                var component = Qt.createComponent("file:MyFile.qml");
                var object  = component.createObject(container, {"x": 0, "y": 0});
    

    i cant call functions in MyFile.qml from C++.

    auto root_object = engine->rootObj().first();
    QMetaObject::invokeMethod(rootObj,"jsFunc",Q_RETURN_ARG(QVariant,retVal),Q_ARG(QVariant,conObj));
    

    Error: QMetaObject::invokeMethod: No such method QQuickWindowQmlImpl_QML_35::jsFunc(QVariant)

    pls help

    Thanks in advance



  • @Alper said:

    auto root_object = engine->rootObj().first();
    QMetaObject::invokeMethod(rootObj,"jsFunc",Q_RETURN_ARG(QVariant,retVal),Q_ARG(QVariant,conObj));
    

    You're trying to call a function named "jsFunc" that is part of root_object (e.g. your ApplicationWindow) but what you want to do is calling a function of an object that is a child of root_object.

    So first, you need to find the child in the hierarchy and then you can call one of its functions. The easiest way to find children is by giving them a unique objectName in QML, like:

    var object  = component.createObject(mainWindow, {"objectName":"someIdentifier"} );
    

    Then, in C++, you can do this:

    QQuickItem *someItem = m_engine->rootObjects().first()->findChild<QQuickItem*>("someIdentifier");
    QMetaObject::invokeMethod(someItem,"jsFunc");
    


  • @Wieland said:

    mainWindow

    Thanks for your answer.
    So i wrote exactly:

    var object  = component.createObject(container, {"objectName":"someIdentifier"} );
    

    and in C++ i did exactly: (it is after loading component into main window)

    QQuickItem *someItem = m_engine->rootObjects().first()->findChild<QQuickItem*>("someIdentifier");
    QMetaObject::invokeMethod(someItem,"jsFunc");
    

    but it not works.
    Have i replace another thing instead of "objectName" or "someIdentifier" ??


  • Moderators

    Hi @Alper
    Have you made sure that the exact object is found ?
    What does qDebug() << someItem print ? It should print the objectName someIdentifier with some other properties.



  • @Wieland
    i solved it!
    i just added a line in MyFile.qml like this:

    Item {
        objectName: "comId"
    ...
    

    main .qml:

    var object  = component.createObject(scr, {"comId":"someId"} );
    

    C++ side:

      QObject *someItem = m_engine->rootObjects().first()->findChild<QObject*>("comId");
      QMetaObject::invokeMethod(someItem,"jsFunc");
    

    Thanks for your help.


  • Moderators

    @Alper Good :)
    But following line doesnot make any sense:
    var object = component.createObject(scr, {"comId":"someId"} );

    You are trying to assign someId to a property named comId which is not present.
    The fact that it worked was due to objectName: "comId" in MyFile.qml which was actually referred when you called findChild.



  • @p3c0

    yes thank you
    it works with:
    var object = component.createObject(scr);
    so can i set dynamic objectName property to component?

    this worked:

    var object  = component.createObject(scr,{"objectName": "newName"});
    

  • Moderators

    @Alper

    so can i set dynamic objectName property to component?

    Yes. @Wieland's suggestion was correct.
    It seems that you passed the wrong parent earlier.


Log in to reply