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

C++ to QML: many variable to exchange - Best solution



  • Dear all,

    I hope you are able to help me to find out an easier way of transfering data retreived from CANBUS (handled in C++) to my QML visualization.

    Short project description:
    As a visualization becomes more and more important, even in industrial and agricultural sectors, I'm developing all my visualization in QT.
    Many people have given positive feedback on this evolution.

    Now for me the only negative point on developping visu in QT is that it is very time consuming to transfer variables from C++ to QML. I suppose there is a much easier way to do so then what I'm doing at the moment.

    Is somebody able to give me a hand with this?

    So what I do:

    First of all I have a program canopenread.cpp where I read all data into variables.
    When data is read, I pass the variable from canopenread.cpp to backend_qml.cpp by SIGNALS and SLOTS.
    When the data is received in backend_qml.cpp I emit a the SIGNAL "certain_data_CHANGED".
    At this point I'm able to use the variable in QML.

    Please see code below:

    part of canopenread.h:

    signals:
        void bflag_heartbeat(bool heartbeat);
    
    

    part of canopenread.cpp:

    // DATA HAS BEEN TRANSFERED TO  "bFlag_Heartbeat" EMIT SIGNAL
    bflag_heartbeat(bFlag_Heartbeat);
    
    

    part of backendqml.h

    class BackendQml : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(bool flagheartbeat READ flagheartbeat WRITE setFlagHeartbeat NOTIFY flagheartbeatChanged)
    
    public:
        explicit BackendQml(QObject *parent = nullptr);
    
    
        // GLOBAL PARAMETERS
        bool flagheartbeat()               const {return m_bFlag_Heartbeat;}
    
    signals:
    
        // GLOBAL PARAMETERS
        void flagheartbeatChanged(bool heartbeat);
     
    
    public slots:
    
        // GLOBAL PARAMETERS
        void setFlagHeartbeat(bool heartbeat);
    
    private:
     
            // GLOBAL PARAMETERS
            bool m_bFlag_Heartbeat;
    };
    
    

    part of backendqml.cpp:

    BackendQml::BackendQml(QObject *parent) : QObject(parent)
    {
     
        // CONSTANT PARAM
        connect(canopen.canopen_read,SIGNAL(bflag_heartbeat(bool)),this, SLOT(setFlagHeartbeat(bool)));
    
    }
    
    
    
    void BackendQml::setFlagHeartbeat(bool heartbeat)
    {
        if(m_bFlag_Heartbeat != heartbeat)
        {
            m_bFlag_Heartbeat = heartbeat;
            emit flagheartbeatChanged(m_bFlag_Heartbeat); 
        }
    }
    

    For 5 variables I'm able to do it this way. But in my last project, I needed to send 55 variables from CANbus to the visualization. This was very time consuming. For an upcoming project I will need to map arround 100 variables.

    Hope somebody is able to help me finding a shorter solution.
    Thanks in advance TMJJ


  • Lifetime Qt Champion

    @TMJJ001 Do these variables have same type? If so you can simply send a vector.
    If not you can pack them into a struct.



  • @jsulm Thanks for response.

    So then I need to create a structure in my canopenread program, create another structure in backendqml and link those by SIGNALS and SLOTS. correct?

    The only dissadvantage I think is that when one variable changes, the complete structure will be "send" to qml. correct?


  • Lifetime Qt Champion

    @TMJJ001 See https://stackoverflow.com/questions/45650277/best-way-to-access-a-cpp-structure-in-qml

    "The only dissadvantage I think is that when one variable changes, the complete structure will be "send" to qml. correct?" - yes, but if you don't want this then you have to use many variables.


  • Moderators

    @TMJJ001
    Just to make sure, are you aware of QtCreators refactor feature for Q_PROPERTIES ?

    you define a Q_PROPERTY(qmlname READ WRITE NOTIFY) etc and then simply right click it with your mouse, select refactor and then "Generate Missing Q_PROPERTY members" than QtCreator will create all functions and member variables for you, automatic in one go.


  • Qt Champions 2018

    Or write a macro that expand to the code you need.



  • You could create a standardized set of mule objects based upon QObject that handle signals of different data types. Then add the appropriate ones to the classes that need them as members or inherit them. Create callbacks that are called by these mule objects with the behavior needed from each class or other structure. If you don't inherit from them you can still use templates on the objects that own the QObjects if you need to simply other boiler plate code.

    I needed the opposite the other day. I had templated classes I wanted to add signals to. So I created a data member mule QObject.

    Edit: One problem with this approach is that object properties would not be unique. Not sure how to get around that.