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. Invoke from C++ a QML function
Forum Updated to NodeBB v4.3 + New Features

Invoke from C++ a QML function

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
3 Posts 2 Posters 1.3k Views 2 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.
  • S Offline
    S Offline
    Sek0
    wrote on last edited by Sek0
    #1

    Hi I am new with Qt. I am using Qt on my RPI3.
    I found a QML example which is Tesla Car instrument cluster. You can access full code from here or here.

    I successfully created project and debug it. Now I am trying to change a value in the QML code from C++ side. There is a timer in my C++ code every 30 seconds I am trying to change speed value in the QML code with using QMetaObject::inokeMethod(): function. I read all examples in here.

    Here is C ++ code

    #ifndef MYTIMER_H
    #define MYTIMER_H
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlComponent>
    #include <QTimer>
    #include <QtDebug>
    class MyTimer : public QObject
    {
        Q_OBJECT
    public:
        MyTimer();
        QTimer *timer;
        int i=0;
    public slots:
        void MySlot();
    };
    #endif // MYTIMER_H
    
    
    #include "mytimer.h"
    MyTimer::MyTimer()
    {
        timer = new QTimer(this);
        connect(timer,SIGNAL(timeout()),this,SLOT(MySlot()));
        timer->start(10000);
    }
    
    void MyTimer::MySlot()
    {
        i++;
        if(i==3)
        {
            i=0;
            QQmlEngine engine;
            QQmlComponent component(&engine,QUrl(QStringLiteral("qrc:/Speedometer.qml")));
            QObject *object = component.create();
            QVariant speeds=100;
            QVariant returnedValue;
            QMetaObject::invokeMethod(object,"speedNeedleValue",
                                       Q_RETURN_ARG(QVariant, returnedValue),
                                       Q_ARG(QVariant, speeds));
             qDebug() << "From QML"<< returnedValue.toString();
             delete object;
        }
    }
    
    
    

    Here is QML

    import QtQuick 2.4
    import QtGraphicalEffects 1.0
    Rectangle {
        color: "transparent"
                  SpeedNeedle {
                      id: speedoNeedle
                           anchors.verticalCenterOffset: 0
                           anchors.centerIn: parent
                           focus: true
                           Keys.onPressed: {
                                    if (event.key == Qt.Key_A) {
                                        speedNeedleValue(100)
                                   }
                  }
    
                  function speedNeedleValue(speeds) {
                      speedoNeedle.value = speeds
                      return ": I am here"
                  }
     }
    

    If I press the "A" button my speedNeedleValue(); function is working. And in debug page I can get the return data return ": I am here".
    Problem is I can't set the speeds argument with invoke function.
    Here is the debug page :
    alt text
    Every time interrupt I can get "I am here". but I also get " JIT is disabled.... " warning too.
    Thank you for your answers.

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      @Sek0 said in Invoke from C++ a QML function:

      QQmlEngine engine;

      You are creating a new (and completely separate!) QML engine every time your timer fires. So your main QML scene never gets the signal.

      Get your main QML engine in MyTimer class, look for your rectangle (you need to give it an objectName and then search for it in QML eingine's children), then invoke the speedNeedleValue function.

      However, this approach is highly unusual. A better way is to expose your MyTimer class to QML, like this:

      engine.rootContext()->setContextProperty("myTimer", &mytimer);
      

      And then in your QML code you can connect to the signal directly:

      Connections {
          target: myTimer
          onTimeout: {
            console.log("I'm here!")
          }
      }
      

      You need to add the timeout() signal to your MyTimer class of course.

      (Z(:^

      S 1 Reply Last reply
      3
      • sierdzioS sierdzio

        @Sek0 said in Invoke from C++ a QML function:

        QQmlEngine engine;

        You are creating a new (and completely separate!) QML engine every time your timer fires. So your main QML scene never gets the signal.

        Get your main QML engine in MyTimer class, look for your rectangle (you need to give it an objectName and then search for it in QML eingine's children), then invoke the speedNeedleValue function.

        However, this approach is highly unusual. A better way is to expose your MyTimer class to QML, like this:

        engine.rootContext()->setContextProperty("myTimer", &mytimer);
        

        And then in your QML code you can connect to the signal directly:

        Connections {
            target: myTimer
            onTimeout: {
              console.log("I'm here!")
            }
        }
        

        You need to add the timeout() signal to your MyTimer class of course.

        S Offline
        S Offline
        Sek0
        wrote on last edited by
        #3

        @sierdzio thank you very much for reply. I will test your comments. I will write after that.

        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