3
votes

I am learning Qt with C++.

Recently I tried to emit a signal from C++ and based on this event change I tried to update something in QML. The emit is not working. In fact debugging the code tells me that the line of code just above the emit and after the emit has worked. But emit itself is not working.

According to my understanding till now, you emit a signal from C++ and on+signal name is used inside the QML to access that event.

What am I doing wrong here ?

Here is the simplified version of the problem:

emitsignal.h

#ifndef EMITSIGNAL_H
#define EMITSIGNAL_H

#include <QObject>

class EmitSignal : public QObject
{
    Q_OBJECT
public:
    explicit EmitSignal(QObject *parent = nullptr);
    int add(int, int);

signals:
    void mySignal();

public slots:
};

#endif // EMITSIGNAL_H

emitsignal.cpp

#include "emitsignal.h"

#include <QDebug>

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

int EmitSignal::add(int x, int y)
{
    int z = x + y;

    qDebug() << z;

    emit mySignal();

    return x + y;
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include "emitsignal.h"

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

    qmlRegisterType<EmitSignal>("com", 1, 0, "EmitSignal");

    EmitSignal em;
    em.add(1,2);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

main.qml

import QtQuick 2.8
import QtQuick.Window 2.2

import com 1.0

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

    EmitSignal {
    id: emitSignal
    onMySignal: console.log('Inside the function')
    }

}
1

1 Answers

3
votes

When qmlRegisterType is used, the type is being registered, so the EmitSignal object with the id:emitSignal is different from the em object (unless the class implements a singleton but in your case it is not), even if the signal is issued for the object em will not be issued for the item with id:emitSignal.

If you want them to be the same object you must use setContextProperty and make the connections with Connections, also you should not call the method that emits the signal before the QML window loads.

main.cpp

#include "emitsignal.h"

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

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

    EmitSignal em;
    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("EmitSignal", &em); // EmitSignal is the id

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;
    em.add(1,2);
    return app.exec();
}

main.qml

import QtQuick 2.8
import QtQuick.Window 2.2

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

    Connections {
        target: EmitSignal
        onMySignal: console.log('Inside the function')
    }
}

References: