Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Calling QML functions from C++ [SOLVED]
Forum Updated to NodeBB v4.3 + New Features

Calling QML functions from C++ [SOLVED]

Scheduled Pinned Locked Moved QML and Qt Quick
12 Posts 2 Posters 11.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    Neon_Burg
    wrote on last edited by
    #3

    The first way gave an error:

    ASSERT failure in QList<T>::at: "index out of range"

    I try to do it like this:

    @QObject * object = engine.rootObjects().value(0)->findChild<QObject*>("algoShow");
    QMetaObject::invokeMethod(object, "insertText",
    Q_ARG(QVariant, QVariant::fromValue(QString("Hello from c++!"))));@

    or like this:

    @QObject * object = engine.findChild<QObject*>("algoShow");@

    and QML:

    @function insertText(msg) {
    console.log(msg);
    }@

    But nothing happened, i think that function was not invoked..

    1 Reply Last reply
    0
    • U Offline
      U Offline
      utcenter
      wrote on last edited by
      #4

      bq. ASSERT failure in QList<T>::at: “index out of range”

      Do you have any QML created at the time you try that? If you don't have the first element in root objects, then you probably don't have anything at all, you HAVE TO HAVE root before you can have anything else. You are probably doing it before any QML is loaded.

      The reason you don't get the out of range error with value() is because this method returns a default constructed value if nothing is found, so you get a null pointer, which is why invoke method doesn't do anything.

      Make sure you have your QML loaded before you try to access it.

      @engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); // or whatever your main QML file is@

      1 Reply Last reply
      0
      • N Offline
        N Offline
        Neon_Burg
        wrote on last edited by
        #5

        Oh, i loaded main,qml, right like you wrote. But then i also created two qml files directly from qml document, in this way:

        in main.cpp I load main.qml:

        @Manager manager;
        engine.load(QUrl(mainPath));
        object = engine.rootObjects().value(0);
        engine.rootContext()->setContextProperty("myObj", &manager);@

        in main.qml I load the second qml file :

        @ApplicationWindow {
        id: mainWindow
        property variant win;

        button {
        ...
        onClicked: {

              var component = Qt.createComponent("qrc:/Smejnost.qml");
              win = component.createObject(mainWindow);
              win.show();
          }
        

        }}@

        Maybe you can suggest a better way, how to load and manage qml files. I'm just a beginner :)

        1 Reply Last reply
        0
        • N Offline
          N Offline
          Neon_Burg
          wrote on last edited by
          #6

          Actualy, this way has one big disadvantage.. I dont see any created qml windows, except the main,qml, when launching the project on android..

          1 Reply Last reply
          0
          • U Offline
            U Offline
            utcenter
            wrote on last edited by
            #7

            Well, you don't honestly expect that you will be able to find the object in C++ main() before it was created in QML, right?

            There is nothing wrong with the way you create the Smejnost component, and regardless of the style of creation, you will always need to have it created before you can locate it with findChild().

            You just have to put your call from C++ to QML in the proper "spot", not simply in main, because it will run immediately after the main component is set, before you have the chance to create extra components from QML.

            But if you really want to put it in main, you can use a signal, add a signal to the ApplicationWindow, in main() find the main object and connect that signal to a free function or lambda which wraps the findChild() and inkoveMethod() call, and from QML emit the signal when Smejnost has been created. This way you will attempt to find the target component only after it is created.

            1 Reply Last reply
            0
            • N Offline
              N Offline
              Neon_Burg
              wrote on last edited by
              #8

              I load qml file, using

              @engine.load(QUrl(QStringLiteral("qrc:/Algo_Show.qml")));
              object = engine.rootObjects().at(0);@

              it worked, but function is still not invoked.

              Error:

              QMetaObject::invokeMethod: No such method QThread::insertText(QVariant)

              1 Reply Last reply
              0
              • N Offline
                N Offline
                Neon_Burg
                wrote on last edited by
                #9

                YES ! I just load qml file like in qt tutorial, and it's worked !

                @QQmlEngine engine;
                QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/Algo_Show.qml")));
                QObject *object = component.create();
                QVariant msg = "Hello from C++";
                QMetaObject::invokeMethod(object, "insertText",
                Q_ARG(QVariant, msg));
                @

                Like i said before, i'm just a begginer ) But the problem solved! Thanks.

                1 Reply Last reply
                0
                • U Offline
                  U Offline
                  utcenter
                  wrote on last edited by
                  #10

                  Yes, you could have created the QML object from C++ as well. All this is for the sake of getting a test to work I guess, you will have to figure out how to lay out your actual application so you avoid the "chicken or egg" paradox.

                  And since you already use Qt, you might as well be using QFile instead of fstream.

                  1 Reply Last reply
                  0
                  • N Offline
                    N Offline
                    Neon_Burg
                    wrote on last edited by
                    #11

                    I got a new paradox, qml file was open, but i cant click at any button or qml object.. Like it's not active.

                    1 Reply Last reply
                    0
                    • N Offline
                      N Offline
                      Neon_Burg
                      wrote on last edited by
                      #12

                      Problem is finaly solved!

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved