Search code examples
c++qtsignalsslots

Qt Signals and Slots - nothing happens


I'm currently trying to connect a QML Signal to a C++ Slot unsuccessfully.

I just had a look on several other examples but I think i didn't got it with how to get the root object of a qml document...

My problem is, it seems like the signal will be sent from the qml file, but not received in the cpp file. There are no errors when I execute this code.

//Counter.h
#ifndef COUNTER_H
#define COUNTER_H

#include <QObject>

class Counter : public QObject
{
    Q_OBJECT

private:
    int counter;

public:
    explicit Counter(QObject *parent = 0);

signals:
    void counterHasChanged(int);

public slots:
    void click();
};

#endif // COUNTER_H


//counter.cpp
#include "counter.h"
#include <QDebug>

Counter::Counter(QObject *parent) :
    QObject(parent)
{
    this->counter = 0;

    qDebug() << "Class Counter created";
}

void Counter::click() {
    this->counter++;

    qDebug() << "clickRegistered() - emit counterHasChanged()";

    emit counterHasChanged(counter);
}



//main.cpp
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include "counter.h"
#include <QObject>
#include <QtQuick>
#include <QDebug>
#include <QQuickItem>
#include <QQmlContext>
#include <QtCore>

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

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/StatesTest2/main.qml"));
    viewer.showExpanded();

    QQuickView view;
    view.setSource(QUrl::fromLocalFile("qml/StatesTest2/main.qml"));

    QObject *item = view.rootObject();

    Counter counter;

    QObject::connect(item, SIGNAL(click()), &counter, SLOT(click()));

    return app.exec();
}



//main.qml
import QtQuick 2.0

Rectangle {
    id: root
    width: 360
    height: 360

    signal click

    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }

    MouseArea {

        anchors.fill: parent
        onClicked: {
            root.click
            console.log("click() qml")
        }
    }

    Text {
        text: "clicks: "
        x: 30
        y: 250
    }

    Text {
        id: counter
        text: "0"
        x: 75
        y: 250
    }
}

I know there are tons of topics like this.. For some reason, no other solution worked for me.. maybe I should change my IDE :D


Solution

  • I suggest you to add counter as a context property.. This requires following changes.

    //Counter.h
    #ifndef COUNTER_H
    #define COUNTER_H
    
    #include <QObject>
    
    class Counter : public QObject
    {
        Q_OBJECT
    
    private:
        int counter;
    
    public:
        explicit Counter(QObject *parent = 0);
    
    signals:
        void counterHasChanged(int Value);
    
    public slots:
        void click();
    };
    
    #endif // COUNTER_H
    

    The Counter.cpp file

    //counter.cpp
    #include "counter.h"
    #include <QDebug>
    
    Counter::Counter(QObject *parent) :
        QObject(parent)
    {
        this->counter = 0;
    
        qDebug() << "Class Counter created";
    }
    
    void Counter::click() {
        this->counter++;
    
        qDebug() << "clickRegistered() - emit counterHasChanged()";
    
        emit counterHasChanged(counter);
    }
    

    The main.cpp file

       //main.cpp
    #include <QtGui/QGuiApplication>
    #include "qtquick2applicationviewer.h"
    #include "counter.h"
    #include <QObject>
    #include <QtQuick>
    #include <QDebug>
    #include <QQuickItem>
    #include <QQmlContext>
    #include <QtCore>
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        Counter counter;
        QtQuick2ApplicationViewer viewer;
        viewer.rootContext()->setContextProperty("counterObj",&counter);
    
        viewer.setMainQmlFile(QStringLiteral("qml/SO_QMLCPPCommunication/main.qml"));
    
    
        viewer.showExpanded();
    
        return app.exec();
    }
    

    And in the qml file, you can access the slot of the Counter object by referring to counterObj.

      //main.qml
    import QtQuick 2.0
    
    Rectangle {
        id: root
        width: 360
        height: 360
    
        signal click
    
        Text {
            text: qsTr("Hello World")
            anchors.centerIn: parent
        }
    
        MouseArea {
    
            anchors.fill: parent
            onClicked: {
                counterObj.click()
                console.log("click() qml")
            }
        }
    
    Text {
        text: "clicks: "
        x: 30
        y: 250
    }
    
    Text {
        id: counter
        text: "0"
        x: 75
        y: 250
    }
    Connections
    {
        id:cppConnection
        target:counterObj
        ignoreUnknownSignals : true
        onCounterHasChanged:{
              //To access signal parameter,please name the parameter.
              console.debug("Counter value changed")
              counter.text = Value
       }
    }
    
    }