Qt slots and passing data

688 views Asked by At

I am trying to make a script in which the Qml code can send data to the c++ script and then executes a function accordingly. This part is working fine, but i also want to send feedback from the executed function back to the Qml.

I have the following code (It is a stripped down example to test the sending of data from Receiver.cpp to the Qml)

Main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "receiver.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    Receiver receiver;

    QQmlContext* ctx = engine.rootContext();
    ctx->setContextProperty("receiver", &receiver);
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));


    return app.exec();
}

Reciever.cpp(Note: I am trying to send the data from this code too. I guess this is where it goes wrong)

#include "receiver.h"
#include <QDebug>

#include <QQmlApplicationEngine> //For sending to QML
#include <QQmlContext> //For sending to QML

Receiver::Receiver(QObject *parent) :
    QObject(parent)
{
}

int counter = 0;

void Receiver::receiveFromQml(int count) {
    qDebug() << "Received in C++ from QML:" << count;

    //For sending to QML start
    QQmlApplicationEngine engine;

    Receiver receiver;

    QQmlContext* ctx = engine.rootContext();
    ctx->setContextProperty("receiver", &receiver);
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

    //For sending to QML end

    receiver.sendToQml(counter); //Send to the QML

    counter++;

}

Reciever.h

#ifndef RECEIVER_H
#define RECEIVER_H

#include <QObject>

class Receiver : public QObject
{
    Q_OBJECT
public:
    explicit Receiver(QObject *parent = 0);

signals:
    void sendToQml(int count);

public slots:
    void receiveFromQml(int count);

};

#endif // RECEIVER_H

Main.qml

import QtQuick 2.2
import QtQuick.Window 2.1

Window {
    id: test
    visible: true
    width: 500
    height: 500

    property variant globalForJs: 10;

    Item {
        Timer {
            interval: 1000; running: true; repeat: true
            onTriggered: console.log("Real text value:", text1.text, " Global for JS:", globalForJs);
        }
    }



    MouseArea {
        anchors.fill: parent
        onClicked: {
            receiver.receiveFromQml(42);
        }

        Text {
            id: text1
            x: 193
            y: 329
            text: globalForJs
            font.pixelSize: 12
        }
    }

    Text {
        text: qsTr("Press me to send a signal to C++")
        anchors.centerIn: parent
    }

    Connections {
        target: receiver
        onSendToQml: {
            console.log("Received in QML from C++: " + count);
            globalForJs = count;
            console.log(text1.text);
            console.log("Real text value:2", text1.text, " Global for JS:", globalForJs);
        }
    }

}

I am using the timer to show the real values of text1 and the global variable GlobalForJs I tried to make but which didn't work. Inside the Connections part it displays that the text in fact changes. But outside of the Connections it does not change.

My best guess is that it is due to the fact that I create a 'new' connection in the receiver.cpp

So in a short summary my question is: How can I send data from receiver.cpp(and in the future other cpp files) to the Qml file and display it?

1

There are 1 answers

4
VP. On BEST ANSWER

Here are a lot of solutions:

  1. Create a signal in C++ code and connect to it in qml to be able to get results from C++ method.

  2. Slots can be not only void but also return a value actually. But in this case it will block your thread and cause a "freeze".

  3. Export an object with which you can interact fully. This is the most suitable way to do such things.