Search code examples
c++qtqmlsignalsslot

Qt C++ Signal to Qml


I am attempting to catch a C++ Qt Signal in Qml. I am able to send a signal, and catching a Qml Signal in Qt is working too; however, I cannot catch a Qt signal in Qml.

Which QObject::connect do i need?

minimal main.cpp:

    #include <QtGui/QGuiApplication>
    #include <QtQml/QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QQuickWindow>
    
    #include "qmlcppapi.h"

    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
        qmlRegisterType<QmlCppApi>("com.handleQmlCppApi",1,0,"HandleQmlCppApi");
        QQmlApplicationEngine engine;
        const QUrl url(QStringLiteral("qrc:/qml/qmlfile.qml"));
        QmlCppApi api;
        engine.rootContext()->setContextProperty("api", &api);
        engine.load(url);
        QObject::connect(&api, &QmlCppApi::testStringSended,
                         &api, &QmlCppApi::printTestString);
        return app.exec();
    }

minimal gmlcppapi.hpp: Slot is only for showing if the signal is emitted

    #ifndef QMLCPPAPI_H
    #define QMLCPPAPI_H
    
    #include <QObject>
    #include <QDebug>
    
    class QmlCppApi : public QObject
    {
        Q_OBJECT
    
    public:
        Q_INVOKABLE void postTestString(QString TestString) {
            qDebug() << "cpp: recieved";
            emit testStringSended(TestString);
        }
    
    public slots:
        void printTestString(QString TestString) {
            qDebug() << "cpp: sended";
        }
    
    signals:
        void testStringSended(QString TestString);
    };
    
    #endif // QMLCPPAPI_H

minimal qmlfile.qml: The ToggleButton should execute the cpp function testStringSended. And the printTestString is firering a emit which should triggers the onTestStringSended

    import QtQuick 2.2
    import QtQuick.Window 2.1
    import QtQuick.Controls 1.4
    import QtQuick.Controls.Styles 1.4
    import QtQuick.Extras 1.4
    import com.handleQmlCppApi 1.0
    
    Window {
        visible: true
        ToggleButton {
            onClicked: {
                console.log("send")
                api.postTestString("TestString")
            }
        }
    
        HandleQmlCppApi {
            onTestStringSended: console.log("recieved")
        }
    }

output:

qml: send
cpp: recieved
cpp: sended

Why is my Qml not receiving the signal?


Solution

  • You have two instances of QmlCppApi that you created. One is in main.cpp, that you call api, and the other is in QML which is the unnamed HandleQmlCppApi object. You only need one of them. To catch a signal from api you need a Connections object, like this:

    Connections {
        target: api
    
        onTestStringSended: console.log("recieved")
    }