Invoke from C++ a QML function



  • 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.


  • Moderators

    @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.



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


Log in to reply
 

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