'C++ signal to QML slot in Qt

I want to send a Signal from C++ to a Slot in my QML File. I already got it working without and primitive type parameters, although if I want to send a QString to my QML Slot I get an error whilst connecting.

I connect in main.cpp

QObject *contentView = rootObject->findChild<QObject*>(QString("contentView"));
QObject::connect(&myObj,      SIGNAL(finishedGatheringDataForItem(QString)), 
                 contentView, SLOT(updateViewWithItem(QString)));

the relavant part of my qml File

Rectangle {
        objectName: "contentView"
        function updateViewWithItem(string) { console.log('got some Items'); }  // slot
}

Error:

Object::connect: No such slot QDeclarativeRectangle_QML_2::updateViewWithItem(QString)


Solution 1:[1]

You should use Connections in this case (maybe it's the only way to connect).

  1. Put your object myObj to QML file by setContextProperty

    qmlVectorForm->rootContext()->setContextProperty("YourObject", myOb);
    
  2. Your signal is

    finishedGatheringDataForItem(QString signalString)
    
  3. In QML file, add Connectios likes below:

    Connections {
        target: YourObject 
        onFinishedGatheringDataForItem: {
            qmlString = signalString
        }
    }
    

Solution 2:[2]

Solution without Connections and any context is by connecting not signal-slot, but signal-signal. Found here. Example code is as follows.

qml:

Window{
    signal qmlSend(string textOut)
    signal qmlReceive(string textIn)
    onQmlReceive:{
      console.log(textIn)
    }
}

Header file of Background class contains

public signals:
    void cppSend(QString textOut);
public slots:
    void cppReceive(QString textIn);

And main.cpp connects them in this way:

1.From qml to cpp:

QObject::connect(qmlRootObject, SIGNAL(qmlSend(QString)),
                backgroundObject, SLOT(cppReceive(QString)));

2.From cpp to qml:

QObject::connect(backgroundObject, SIGNAL(cppSend(QString)),
                 qmlRootObject, SIGNAL(qmlReceive(QString)));

Solution 3:[3]

I have tried a lot of solutions to succeed in just update QML from a C++ signal but many did not work. This solution works and has been tested, it is based on this answer: https://stackoverflow.com/a/59502860/2486332 (by @Adriano Campos)

You can send data from C++ to qml using signals, like this:

main.cpp:

#include <QQmlContext>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    // Class init
    YourClass yourObject;

    // Embedding C++ Objects into QML with Context Properties
    QQmlContext* ctx = engine.rootContext();
    ctx->setContextProperty("yourObject", &yourObject);

    return app.exec();
}

main.qml:

import QtQuick 2.6

Window {
    id: mainWindow

    Connections {
        target: yourObject
        onSignalData: {
            console.log("Data: " + signal_param)
            textToChange.text = "Changed to: " + signal_param
        }
    }

    Text {
        id: textToChange
        text: "beforeChange"
    }
}

yourClass.h:

class YourClass : public QObject
{
Q_OBJECT
signals:
    // Signal from YourClass
    void signalData(QString signal_param);
}

yourClass.cpp:

emit signalData("Hello QML"); // Signal from yourClass

A complete tutorial about "How to Expose a Qt C++ Class with Signals and Slots to QML" is available on this page: https://felgo.com/cross-platform-development/how-to-expose-a-qt-cpp-class-with-signals-and-slots-to-qml

Solution 4:[4]

For those who also stumbled upon this question, I want to say that Everything is much simpler. You just need the signal from C++ to have QVariant arguments. For example:

QObject::connect(&recipient, SIGNAL(resTalk(QVariant)), engine.rootObjects().at(0)->findChild<QObject*>("winSettings"),
                     SLOT(showWithErrorNetwork(QVariant)));

My signal is declared like this:

signals:
    void resTalk(QVariant res);

So I'm calling the signal:

emit resTalk(true); //For more complex types, use  'emit yourSignal(QVariant(yourArg))'

And here is the slot I have in QML:

    function showWithErrorNetwork(isNoError=false) {
        if(!isNoError) {
            visible = true
            warningText.text = "Network error. Check the data."
            warningText.visible = true
        }
    }

Solution 5:[5]

Why not use rootContext?

in c++ side you have:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

//--------------------------------------------------------
#include <myClass.h>
//--------------------------------------------------------

int main(int argc, char *argv[])
{

    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;

    //--------------------------------------------------------
    myClass * myobj = new myClass(&app);
    //--------------------------------------------------------

    //--------------------------------------------------------
    engine.rootContext()->setContextProperty("myobj",myobj);
    //--------------------------------------------------------

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);
    return app.exec();
}

and in qml side you have:

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    id: window
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    //--------------------------------------------------------
    Component.onCompleted: {
       myobj.onSomeSignal.connect(signalHandling) 
    }
    //--------------------------------------------------------

    //--------------------------------------------------------
    function signalHandling(){
       console.log("Signal emitted from c++ side")
    }
    //--------------------------------------------------------
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 zwcloud
Solution 2
Solution 3 quent
Solution 4 ?????? ????????
Solution 5 Reza Soleimani