QML function invoked from C++ not able to update element












-2















I am invoking a QML function from C++. Issue is the QML function cannot update a QML element when invoked from C++. below is code:



In main.qml:



import QtQuick 2.0

function myQmlFunction(msg) {
console.log("Got message:", msg)
textbox.text = msg
return "some return value"
}

Text {
id: textbox
text: "nothing"
}


In main.cpp:



QQmlEngine engine;
QQmlComponent component(&engine, "MyItem.qml");
QObject *object = component.create();

QVariant returnedValue;
QVariant msg = "Hello from C++";
QMetaObject::invokeMethod(object, "myQmlFunction",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));

qDebug() << "QML function returned:" << returnedValue.toString();
delete object;


The textbox element is just a regular text, and the text inside it remains "nothing", instead of the expected "Hello from C++".



Any ideas on how to solve this issue or in successfully passing arguments from C++ to QML?










share|improve this question




















  • 2





    please improve your example and provide a Minimal, Complete, and Verifiable example, there are many things that are not defined and that are possibly causing the error. On the other hand you are creating a new item with component.create(); that may differ from the MyItem created elsewhere, even with your update your code does not make sense.

    – eyllanesc
    Nov 15 '18 at 16:08






  • 1





    main.qml or MyItem.qml????

    – eyllanesc
    Nov 15 '18 at 16:09











  • I see that you are creating a MyItem and instantly you are destroying it so it makes me presume that the visible MyItem is different and you have changed the text of another MyItem that you delete it instantly. every time you call component.create() you are creating another MyItem other than the one that is probably in your window. How do you create the window?

    – eyllanesc
    Nov 15 '18 at 16:12













  • On second thoughts, after posting my answer, sounds you're having an XY problem. @Sparkskie

    – TrebuchetMS
    Nov 16 '18 at 10:05
















-2















I am invoking a QML function from C++. Issue is the QML function cannot update a QML element when invoked from C++. below is code:



In main.qml:



import QtQuick 2.0

function myQmlFunction(msg) {
console.log("Got message:", msg)
textbox.text = msg
return "some return value"
}

Text {
id: textbox
text: "nothing"
}


In main.cpp:



QQmlEngine engine;
QQmlComponent component(&engine, "MyItem.qml");
QObject *object = component.create();

QVariant returnedValue;
QVariant msg = "Hello from C++";
QMetaObject::invokeMethod(object, "myQmlFunction",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));

qDebug() << "QML function returned:" << returnedValue.toString();
delete object;


The textbox element is just a regular text, and the text inside it remains "nothing", instead of the expected "Hello from C++".



Any ideas on how to solve this issue or in successfully passing arguments from C++ to QML?










share|improve this question




















  • 2





    please improve your example and provide a Minimal, Complete, and Verifiable example, there are many things that are not defined and that are possibly causing the error. On the other hand you are creating a new item with component.create(); that may differ from the MyItem created elsewhere, even with your update your code does not make sense.

    – eyllanesc
    Nov 15 '18 at 16:08






  • 1





    main.qml or MyItem.qml????

    – eyllanesc
    Nov 15 '18 at 16:09











  • I see that you are creating a MyItem and instantly you are destroying it so it makes me presume that the visible MyItem is different and you have changed the text of another MyItem that you delete it instantly. every time you call component.create() you are creating another MyItem other than the one that is probably in your window. How do you create the window?

    – eyllanesc
    Nov 15 '18 at 16:12













  • On second thoughts, after posting my answer, sounds you're having an XY problem. @Sparkskie

    – TrebuchetMS
    Nov 16 '18 at 10:05














-2












-2








-2








I am invoking a QML function from C++. Issue is the QML function cannot update a QML element when invoked from C++. below is code:



In main.qml:



import QtQuick 2.0

function myQmlFunction(msg) {
console.log("Got message:", msg)
textbox.text = msg
return "some return value"
}

Text {
id: textbox
text: "nothing"
}


In main.cpp:



QQmlEngine engine;
QQmlComponent component(&engine, "MyItem.qml");
QObject *object = component.create();

QVariant returnedValue;
QVariant msg = "Hello from C++";
QMetaObject::invokeMethod(object, "myQmlFunction",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));

qDebug() << "QML function returned:" << returnedValue.toString();
delete object;


The textbox element is just a regular text, and the text inside it remains "nothing", instead of the expected "Hello from C++".



Any ideas on how to solve this issue or in successfully passing arguments from C++ to QML?










share|improve this question
















I am invoking a QML function from C++. Issue is the QML function cannot update a QML element when invoked from C++. below is code:



In main.qml:



import QtQuick 2.0

function myQmlFunction(msg) {
console.log("Got message:", msg)
textbox.text = msg
return "some return value"
}

Text {
id: textbox
text: "nothing"
}


In main.cpp:



QQmlEngine engine;
QQmlComponent component(&engine, "MyItem.qml");
QObject *object = component.create();

QVariant returnedValue;
QVariant msg = "Hello from C++";
QMetaObject::invokeMethod(object, "myQmlFunction",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));

qDebug() << "QML function returned:" << returnedValue.toString();
delete object;


The textbox element is just a regular text, and the text inside it remains "nothing", instead of the expected "Hello from C++".



Any ideas on how to solve this issue or in successfully passing arguments from C++ to QML?







c++ qt qml qqmlengine






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 10:08









TrebuchetMS

3,10011125




3,10011125










asked Nov 15 '18 at 16:01









SparkskieSparkskie

11




11








  • 2





    please improve your example and provide a Minimal, Complete, and Verifiable example, there are many things that are not defined and that are possibly causing the error. On the other hand you are creating a new item with component.create(); that may differ from the MyItem created elsewhere, even with your update your code does not make sense.

    – eyllanesc
    Nov 15 '18 at 16:08






  • 1





    main.qml or MyItem.qml????

    – eyllanesc
    Nov 15 '18 at 16:09











  • I see that you are creating a MyItem and instantly you are destroying it so it makes me presume that the visible MyItem is different and you have changed the text of another MyItem that you delete it instantly. every time you call component.create() you are creating another MyItem other than the one that is probably in your window. How do you create the window?

    – eyllanesc
    Nov 15 '18 at 16:12













  • On second thoughts, after posting my answer, sounds you're having an XY problem. @Sparkskie

    – TrebuchetMS
    Nov 16 '18 at 10:05














  • 2





    please improve your example and provide a Minimal, Complete, and Verifiable example, there are many things that are not defined and that are possibly causing the error. On the other hand you are creating a new item with component.create(); that may differ from the MyItem created elsewhere, even with your update your code does not make sense.

    – eyllanesc
    Nov 15 '18 at 16:08






  • 1





    main.qml or MyItem.qml????

    – eyllanesc
    Nov 15 '18 at 16:09











  • I see that you are creating a MyItem and instantly you are destroying it so it makes me presume that the visible MyItem is different and you have changed the text of another MyItem that you delete it instantly. every time you call component.create() you are creating another MyItem other than the one that is probably in your window. How do you create the window?

    – eyllanesc
    Nov 15 '18 at 16:12













  • On second thoughts, after posting my answer, sounds you're having an XY problem. @Sparkskie

    – TrebuchetMS
    Nov 16 '18 at 10:05








2




2





please improve your example and provide a Minimal, Complete, and Verifiable example, there are many things that are not defined and that are possibly causing the error. On the other hand you are creating a new item with component.create(); that may differ from the MyItem created elsewhere, even with your update your code does not make sense.

– eyllanesc
Nov 15 '18 at 16:08





please improve your example and provide a Minimal, Complete, and Verifiable example, there are many things that are not defined and that are possibly causing the error. On the other hand you are creating a new item with component.create(); that may differ from the MyItem created elsewhere, even with your update your code does not make sense.

– eyllanesc
Nov 15 '18 at 16:08




1




1





main.qml or MyItem.qml????

– eyllanesc
Nov 15 '18 at 16:09





main.qml or MyItem.qml????

– eyllanesc
Nov 15 '18 at 16:09













I see that you are creating a MyItem and instantly you are destroying it so it makes me presume that the visible MyItem is different and you have changed the text of another MyItem that you delete it instantly. every time you call component.create() you are creating another MyItem other than the one that is probably in your window. How do you create the window?

– eyllanesc
Nov 15 '18 at 16:12







I see that you are creating a MyItem and instantly you are destroying it so it makes me presume that the visible MyItem is different and you have changed the text of another MyItem that you delete it instantly. every time you call component.create() you are creating another MyItem other than the one that is probably in your window. How do you create the window?

– eyllanesc
Nov 15 '18 at 16:12















On second thoughts, after posting my answer, sounds you're having an XY problem. @Sparkskie

– TrebuchetMS
Nov 16 '18 at 10:05





On second thoughts, after posting my answer, sounds you're having an XY problem. @Sparkskie

– TrebuchetMS
Nov 16 '18 at 10:05












2 Answers
2






active

oldest

votes


















0














Lé Code



Qml



I'll assume that the qml code given actually belongs to MyItem.qml instead of main.qml.



Your Qml file generated an compile-time error. Functions should be placed inside an object, like so



// MyItem.qml
import QtQuick 2.0

Text {
id: textbox
text: "nothing"

function myQmlFunction(msg) {
console.log("Got message:", msg)
textbox.text = msg
return "some return value"
}
}


I'm not sure how you were able to compile your project without generating an error, but I'm guessing either




  1. Your QtCreator/Qt version is not the same as mine (highly unlikely the cause); or

  2. You were try to making your code minimal and originally had a parent.


I'm sure you have a sufficient understanding about Qml so I'm not going to go deep into this.



C++



On the C++ side, I had to fiddle around with debug output to see what's wrong. Here's my main.cpp:



// main.cpp
#include <QApplication>
#include <QDebug>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QQuickItem>

int main(int argc, char *argv)
{
QApplication app(argc, argv); // Qt requires an instance of QApplication


QQmlEngine *engine = new QQmlEngine;

QString projectPath = "/Users/user/full/path/to/your/project"; // I'm on a Mac, but replace
// with the appropriate path to your project

// QQmlComponent component(engine, "MyItem.qml"); // this didn't work for me and
// set component.status() to QQmlComponent::Error

QQmlComponent component(engine, projectPath + "/qml/MyItem.qml"); // use full path

qDebug() << "Status:" << component.status();
if (component.status() == QQmlComponent::Error)
qDebug() << "Errors:" << component.errors();
else if (component.status() != QQmlComponent::Ready)
{
qDebug() << "Component is not ready!";
return 0;
}

QObject *object = component.create();
if (!object) { qDebug() << "Object creation failed!"; return 0; }

QQuickItem *item = qobject_cast<QQuickItem*>(object); // adding this didn't change much
// but this could be crucial

QVariant returnedValue;
QVariant msg = "Hello from C++";

bool success = QMetaObject::invokeMethod(item, "myQmlFunction", // replace `object` with `item`
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));

if (success)
qDebug() << "QML function returned:" << returnedValue.toString();
else
qDebug() << "QMetaObject::invokeMethod returned false";

delete object;

return 0;
}


Output



The output I received on a successful build, with a successful object creation was



Status: QQmlComponent::Status(Ready)
Object: MyItem_QMLTYPE_0(0x7f8d4ae8b640)
qml: Got message: Hello from C++
QML function returned: "some return value"


I haven't yet checked whether the text changed in your Qml textbox. (Didn't bother to. It'll require more changes to the C++ code and this answer is already long enough. I was also confident that nothing'll go wrong, so ¯_(ツ)_/¯).





Lé Non-Code



What if I don't want to use a raw file path?



If you're meh about using a raw file path (e.g. /Users/whoami/ugly/looking/path) in



QString projectPath = "/Users/user/full/path/to/your/project";


You can add this to your .pro file:



DEFINES += SOURCE_PATH=$$PWD


and set projectPath to



QString projectPath = QT_STRINGIFY(SOURCE_PATH);


This idea was borrowed from a forum thread.





Assumptions



Throughout my answer, I have assumed that your project hierarchy resembles



/./
|- myProject.pro
|- main.cpp
|- qml/
|- MyItem.qml


The essential thing is that you use your full path to your qml item. If you do find another to reference it (maybe using QUrl?) then do post a comment about it.





Further Reading



Check out the details section of the QQmlComponent class and QQmlComponent::create member function. Reading these led me to know which values to debug and what to look out for.






share|improve this answer

































    0














    Thanks for helping out,
    I debugged it as well and the textbox.text was being overwritten with "Hello from C++" without the text in the window to be updated.



    like eyllanesc suggested, I was creating a new engine object other than the already displayed window. (created elsewhere in the code)



    after referencing the same object, the problem was solved.






    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53323350%2fqml-function-invoked-from-c-not-able-to-update-element%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      0














      Lé Code



      Qml



      I'll assume that the qml code given actually belongs to MyItem.qml instead of main.qml.



      Your Qml file generated an compile-time error. Functions should be placed inside an object, like so



      // MyItem.qml
      import QtQuick 2.0

      Text {
      id: textbox
      text: "nothing"

      function myQmlFunction(msg) {
      console.log("Got message:", msg)
      textbox.text = msg
      return "some return value"
      }
      }


      I'm not sure how you were able to compile your project without generating an error, but I'm guessing either




      1. Your QtCreator/Qt version is not the same as mine (highly unlikely the cause); or

      2. You were try to making your code minimal and originally had a parent.


      I'm sure you have a sufficient understanding about Qml so I'm not going to go deep into this.



      C++



      On the C++ side, I had to fiddle around with debug output to see what's wrong. Here's my main.cpp:



      // main.cpp
      #include <QApplication>
      #include <QDebug>
      #include <QQmlApplicationEngine>
      #include <QQmlComponent>
      #include <QQuickItem>

      int main(int argc, char *argv)
      {
      QApplication app(argc, argv); // Qt requires an instance of QApplication


      QQmlEngine *engine = new QQmlEngine;

      QString projectPath = "/Users/user/full/path/to/your/project"; // I'm on a Mac, but replace
      // with the appropriate path to your project

      // QQmlComponent component(engine, "MyItem.qml"); // this didn't work for me and
      // set component.status() to QQmlComponent::Error

      QQmlComponent component(engine, projectPath + "/qml/MyItem.qml"); // use full path

      qDebug() << "Status:" << component.status();
      if (component.status() == QQmlComponent::Error)
      qDebug() << "Errors:" << component.errors();
      else if (component.status() != QQmlComponent::Ready)
      {
      qDebug() << "Component is not ready!";
      return 0;
      }

      QObject *object = component.create();
      if (!object) { qDebug() << "Object creation failed!"; return 0; }

      QQuickItem *item = qobject_cast<QQuickItem*>(object); // adding this didn't change much
      // but this could be crucial

      QVariant returnedValue;
      QVariant msg = "Hello from C++";

      bool success = QMetaObject::invokeMethod(item, "myQmlFunction", // replace `object` with `item`
      Q_RETURN_ARG(QVariant, returnedValue),
      Q_ARG(QVariant, msg));

      if (success)
      qDebug() << "QML function returned:" << returnedValue.toString();
      else
      qDebug() << "QMetaObject::invokeMethod returned false";

      delete object;

      return 0;
      }


      Output



      The output I received on a successful build, with a successful object creation was



      Status: QQmlComponent::Status(Ready)
      Object: MyItem_QMLTYPE_0(0x7f8d4ae8b640)
      qml: Got message: Hello from C++
      QML function returned: "some return value"


      I haven't yet checked whether the text changed in your Qml textbox. (Didn't bother to. It'll require more changes to the C++ code and this answer is already long enough. I was also confident that nothing'll go wrong, so ¯_(ツ)_/¯).





      Lé Non-Code



      What if I don't want to use a raw file path?



      If you're meh about using a raw file path (e.g. /Users/whoami/ugly/looking/path) in



      QString projectPath = "/Users/user/full/path/to/your/project";


      You can add this to your .pro file:



      DEFINES += SOURCE_PATH=$$PWD


      and set projectPath to



      QString projectPath = QT_STRINGIFY(SOURCE_PATH);


      This idea was borrowed from a forum thread.





      Assumptions



      Throughout my answer, I have assumed that your project hierarchy resembles



      /./
      |- myProject.pro
      |- main.cpp
      |- qml/
      |- MyItem.qml


      The essential thing is that you use your full path to your qml item. If you do find another to reference it (maybe using QUrl?) then do post a comment about it.





      Further Reading



      Check out the details section of the QQmlComponent class and QQmlComponent::create member function. Reading these led me to know which values to debug and what to look out for.






      share|improve this answer






























        0














        Lé Code



        Qml



        I'll assume that the qml code given actually belongs to MyItem.qml instead of main.qml.



        Your Qml file generated an compile-time error. Functions should be placed inside an object, like so



        // MyItem.qml
        import QtQuick 2.0

        Text {
        id: textbox
        text: "nothing"

        function myQmlFunction(msg) {
        console.log("Got message:", msg)
        textbox.text = msg
        return "some return value"
        }
        }


        I'm not sure how you were able to compile your project without generating an error, but I'm guessing either




        1. Your QtCreator/Qt version is not the same as mine (highly unlikely the cause); or

        2. You were try to making your code minimal and originally had a parent.


        I'm sure you have a sufficient understanding about Qml so I'm not going to go deep into this.



        C++



        On the C++ side, I had to fiddle around with debug output to see what's wrong. Here's my main.cpp:



        // main.cpp
        #include <QApplication>
        #include <QDebug>
        #include <QQmlApplicationEngine>
        #include <QQmlComponent>
        #include <QQuickItem>

        int main(int argc, char *argv)
        {
        QApplication app(argc, argv); // Qt requires an instance of QApplication


        QQmlEngine *engine = new QQmlEngine;

        QString projectPath = "/Users/user/full/path/to/your/project"; // I'm on a Mac, but replace
        // with the appropriate path to your project

        // QQmlComponent component(engine, "MyItem.qml"); // this didn't work for me and
        // set component.status() to QQmlComponent::Error

        QQmlComponent component(engine, projectPath + "/qml/MyItem.qml"); // use full path

        qDebug() << "Status:" << component.status();
        if (component.status() == QQmlComponent::Error)
        qDebug() << "Errors:" << component.errors();
        else if (component.status() != QQmlComponent::Ready)
        {
        qDebug() << "Component is not ready!";
        return 0;
        }

        QObject *object = component.create();
        if (!object) { qDebug() << "Object creation failed!"; return 0; }

        QQuickItem *item = qobject_cast<QQuickItem*>(object); // adding this didn't change much
        // but this could be crucial

        QVariant returnedValue;
        QVariant msg = "Hello from C++";

        bool success = QMetaObject::invokeMethod(item, "myQmlFunction", // replace `object` with `item`
        Q_RETURN_ARG(QVariant, returnedValue),
        Q_ARG(QVariant, msg));

        if (success)
        qDebug() << "QML function returned:" << returnedValue.toString();
        else
        qDebug() << "QMetaObject::invokeMethod returned false";

        delete object;

        return 0;
        }


        Output



        The output I received on a successful build, with a successful object creation was



        Status: QQmlComponent::Status(Ready)
        Object: MyItem_QMLTYPE_0(0x7f8d4ae8b640)
        qml: Got message: Hello from C++
        QML function returned: "some return value"


        I haven't yet checked whether the text changed in your Qml textbox. (Didn't bother to. It'll require more changes to the C++ code and this answer is already long enough. I was also confident that nothing'll go wrong, so ¯_(ツ)_/¯).





        Lé Non-Code



        What if I don't want to use a raw file path?



        If you're meh about using a raw file path (e.g. /Users/whoami/ugly/looking/path) in



        QString projectPath = "/Users/user/full/path/to/your/project";


        You can add this to your .pro file:



        DEFINES += SOURCE_PATH=$$PWD


        and set projectPath to



        QString projectPath = QT_STRINGIFY(SOURCE_PATH);


        This idea was borrowed from a forum thread.





        Assumptions



        Throughout my answer, I have assumed that your project hierarchy resembles



        /./
        |- myProject.pro
        |- main.cpp
        |- qml/
        |- MyItem.qml


        The essential thing is that you use your full path to your qml item. If you do find another to reference it (maybe using QUrl?) then do post a comment about it.





        Further Reading



        Check out the details section of the QQmlComponent class and QQmlComponent::create member function. Reading these led me to know which values to debug and what to look out for.






        share|improve this answer




























          0












          0








          0







          Lé Code



          Qml



          I'll assume that the qml code given actually belongs to MyItem.qml instead of main.qml.



          Your Qml file generated an compile-time error. Functions should be placed inside an object, like so



          // MyItem.qml
          import QtQuick 2.0

          Text {
          id: textbox
          text: "nothing"

          function myQmlFunction(msg) {
          console.log("Got message:", msg)
          textbox.text = msg
          return "some return value"
          }
          }


          I'm not sure how you were able to compile your project without generating an error, but I'm guessing either




          1. Your QtCreator/Qt version is not the same as mine (highly unlikely the cause); or

          2. You were try to making your code minimal and originally had a parent.


          I'm sure you have a sufficient understanding about Qml so I'm not going to go deep into this.



          C++



          On the C++ side, I had to fiddle around with debug output to see what's wrong. Here's my main.cpp:



          // main.cpp
          #include <QApplication>
          #include <QDebug>
          #include <QQmlApplicationEngine>
          #include <QQmlComponent>
          #include <QQuickItem>

          int main(int argc, char *argv)
          {
          QApplication app(argc, argv); // Qt requires an instance of QApplication


          QQmlEngine *engine = new QQmlEngine;

          QString projectPath = "/Users/user/full/path/to/your/project"; // I'm on a Mac, but replace
          // with the appropriate path to your project

          // QQmlComponent component(engine, "MyItem.qml"); // this didn't work for me and
          // set component.status() to QQmlComponent::Error

          QQmlComponent component(engine, projectPath + "/qml/MyItem.qml"); // use full path

          qDebug() << "Status:" << component.status();
          if (component.status() == QQmlComponent::Error)
          qDebug() << "Errors:" << component.errors();
          else if (component.status() != QQmlComponent::Ready)
          {
          qDebug() << "Component is not ready!";
          return 0;
          }

          QObject *object = component.create();
          if (!object) { qDebug() << "Object creation failed!"; return 0; }

          QQuickItem *item = qobject_cast<QQuickItem*>(object); // adding this didn't change much
          // but this could be crucial

          QVariant returnedValue;
          QVariant msg = "Hello from C++";

          bool success = QMetaObject::invokeMethod(item, "myQmlFunction", // replace `object` with `item`
          Q_RETURN_ARG(QVariant, returnedValue),
          Q_ARG(QVariant, msg));

          if (success)
          qDebug() << "QML function returned:" << returnedValue.toString();
          else
          qDebug() << "QMetaObject::invokeMethod returned false";

          delete object;

          return 0;
          }


          Output



          The output I received on a successful build, with a successful object creation was



          Status: QQmlComponent::Status(Ready)
          Object: MyItem_QMLTYPE_0(0x7f8d4ae8b640)
          qml: Got message: Hello from C++
          QML function returned: "some return value"


          I haven't yet checked whether the text changed in your Qml textbox. (Didn't bother to. It'll require more changes to the C++ code and this answer is already long enough. I was also confident that nothing'll go wrong, so ¯_(ツ)_/¯).





          Lé Non-Code



          What if I don't want to use a raw file path?



          If you're meh about using a raw file path (e.g. /Users/whoami/ugly/looking/path) in



          QString projectPath = "/Users/user/full/path/to/your/project";


          You can add this to your .pro file:



          DEFINES += SOURCE_PATH=$$PWD


          and set projectPath to



          QString projectPath = QT_STRINGIFY(SOURCE_PATH);


          This idea was borrowed from a forum thread.





          Assumptions



          Throughout my answer, I have assumed that your project hierarchy resembles



          /./
          |- myProject.pro
          |- main.cpp
          |- qml/
          |- MyItem.qml


          The essential thing is that you use your full path to your qml item. If you do find another to reference it (maybe using QUrl?) then do post a comment about it.





          Further Reading



          Check out the details section of the QQmlComponent class and QQmlComponent::create member function. Reading these led me to know which values to debug and what to look out for.






          share|improve this answer















          Lé Code



          Qml



          I'll assume that the qml code given actually belongs to MyItem.qml instead of main.qml.



          Your Qml file generated an compile-time error. Functions should be placed inside an object, like so



          // MyItem.qml
          import QtQuick 2.0

          Text {
          id: textbox
          text: "nothing"

          function myQmlFunction(msg) {
          console.log("Got message:", msg)
          textbox.text = msg
          return "some return value"
          }
          }


          I'm not sure how you were able to compile your project without generating an error, but I'm guessing either




          1. Your QtCreator/Qt version is not the same as mine (highly unlikely the cause); or

          2. You were try to making your code minimal and originally had a parent.


          I'm sure you have a sufficient understanding about Qml so I'm not going to go deep into this.



          C++



          On the C++ side, I had to fiddle around with debug output to see what's wrong. Here's my main.cpp:



          // main.cpp
          #include <QApplication>
          #include <QDebug>
          #include <QQmlApplicationEngine>
          #include <QQmlComponent>
          #include <QQuickItem>

          int main(int argc, char *argv)
          {
          QApplication app(argc, argv); // Qt requires an instance of QApplication


          QQmlEngine *engine = new QQmlEngine;

          QString projectPath = "/Users/user/full/path/to/your/project"; // I'm on a Mac, but replace
          // with the appropriate path to your project

          // QQmlComponent component(engine, "MyItem.qml"); // this didn't work for me and
          // set component.status() to QQmlComponent::Error

          QQmlComponent component(engine, projectPath + "/qml/MyItem.qml"); // use full path

          qDebug() << "Status:" << component.status();
          if (component.status() == QQmlComponent::Error)
          qDebug() << "Errors:" << component.errors();
          else if (component.status() != QQmlComponent::Ready)
          {
          qDebug() << "Component is not ready!";
          return 0;
          }

          QObject *object = component.create();
          if (!object) { qDebug() << "Object creation failed!"; return 0; }

          QQuickItem *item = qobject_cast<QQuickItem*>(object); // adding this didn't change much
          // but this could be crucial

          QVariant returnedValue;
          QVariant msg = "Hello from C++";

          bool success = QMetaObject::invokeMethod(item, "myQmlFunction", // replace `object` with `item`
          Q_RETURN_ARG(QVariant, returnedValue),
          Q_ARG(QVariant, msg));

          if (success)
          qDebug() << "QML function returned:" << returnedValue.toString();
          else
          qDebug() << "QMetaObject::invokeMethod returned false";

          delete object;

          return 0;
          }


          Output



          The output I received on a successful build, with a successful object creation was



          Status: QQmlComponent::Status(Ready)
          Object: MyItem_QMLTYPE_0(0x7f8d4ae8b640)
          qml: Got message: Hello from C++
          QML function returned: "some return value"


          I haven't yet checked whether the text changed in your Qml textbox. (Didn't bother to. It'll require more changes to the C++ code and this answer is already long enough. I was also confident that nothing'll go wrong, so ¯_(ツ)_/¯).





          Lé Non-Code



          What if I don't want to use a raw file path?



          If you're meh about using a raw file path (e.g. /Users/whoami/ugly/looking/path) in



          QString projectPath = "/Users/user/full/path/to/your/project";


          You can add this to your .pro file:



          DEFINES += SOURCE_PATH=$$PWD


          and set projectPath to



          QString projectPath = QT_STRINGIFY(SOURCE_PATH);


          This idea was borrowed from a forum thread.





          Assumptions



          Throughout my answer, I have assumed that your project hierarchy resembles



          /./
          |- myProject.pro
          |- main.cpp
          |- qml/
          |- MyItem.qml


          The essential thing is that you use your full path to your qml item. If you do find another to reference it (maybe using QUrl?) then do post a comment about it.





          Further Reading



          Check out the details section of the QQmlComponent class and QQmlComponent::create member function. Reading these led me to know which values to debug and what to look out for.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 16 '18 at 10:00

























          answered Nov 16 '18 at 9:54









          TrebuchetMSTrebuchetMS

          3,10011125




          3,10011125

























              0














              Thanks for helping out,
              I debugged it as well and the textbox.text was being overwritten with "Hello from C++" without the text in the window to be updated.



              like eyllanesc suggested, I was creating a new engine object other than the already displayed window. (created elsewhere in the code)



              after referencing the same object, the problem was solved.






              share|improve this answer




























                0














                Thanks for helping out,
                I debugged it as well and the textbox.text was being overwritten with "Hello from C++" without the text in the window to be updated.



                like eyllanesc suggested, I was creating a new engine object other than the already displayed window. (created elsewhere in the code)



                after referencing the same object, the problem was solved.






                share|improve this answer


























                  0












                  0








                  0







                  Thanks for helping out,
                  I debugged it as well and the textbox.text was being overwritten with "Hello from C++" without the text in the window to be updated.



                  like eyllanesc suggested, I was creating a new engine object other than the already displayed window. (created elsewhere in the code)



                  after referencing the same object, the problem was solved.






                  share|improve this answer













                  Thanks for helping out,
                  I debugged it as well and the textbox.text was being overwritten with "Hello from C++" without the text in the window to be updated.



                  like eyllanesc suggested, I was creating a new engine object other than the already displayed window. (created elsewhere in the code)



                  after referencing the same object, the problem was solved.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 16 '18 at 14:03









                  SparkskieSparkskie

                  11




                  11






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53323350%2fqml-function-invoked-from-c-not-able-to-update-element%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Florida Star v. B. J. F.

                      Danny Elfman

                      Lugert, Oklahoma