Search code examples
c++qtqmlsignals-slots

Can't figure out the right way to bind signals from qml to cpp slots


I'm using QT 5.7. My main.qml file's root element is 'ApplicationWindow'(which btw always underlines visible, width and height as invalid properties even though they work. I'd like to know a fix for it or the proper way to do this since I can't edit it in designer). This is its code:

ApplicationWindow {
visible: true
width: 640
height: 480
    Rectangle{
    signal mSend()
    anchors.fill: parent
        Button{
            id: bSend
                onClicked: {
                    parent.mSend()
                }
        }
    }
}

Now I'm trying to bind the mSend signal to a CPP slot this way:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
#include <QObject>
#include <QQuickView>
#include <QQuickItem>

class Chat: public QObject{
    Q_OBJECT

    public Q_SLOTS:
    void sendMessage(){
        qDebug() << "CPP SLOT sendMessage called";
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));

    QQuickView view(&engine, Q_NULLPTR);
    QObject *item = view.rootObject();
    Chat chat;
    if(item){
        qDebug() << "Item found";
        QObject::connect(item, SIGNAL(mSend()), &chat, SLOT(sendMessage()));
    }else{
        qDebug() << "item is null";
    }

    return app.exec();
}
#include "main.moc"

But the result is Item is null. I've been following this guide but I'm unable to tinker with QMLApplicationEngine and ApplicationWindow in QML.

TIA

NOTE: I'm using Q_SLOTS because I'm also using Boost to incorporate Socket IO library.


Solution

  • You should move the signal from the Rectangle to the root object:

    import QtQuick 2.5
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.4
    
    ApplicationWindow {
      id: appWindow
      visible: true
      width: 640
      height: 480
      signal mSend()
      Rectangle{
        anchors.fill: parent
        Button{
          id: bSend
          onClicked: {
            appWindow.mSend()
          }
        }
      }
    }
    

    The root object is directly available through the QQmlApplicationEngine

    QGuiApplication app(argc, argv);
    
    QQmlApplicationEngine engine;
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    
    QObject *item = engine.rootObjects().first();
    Chat chat;
    if(item){
        qDebug() << "Item found";
        QObject::connect(item, SIGNAL(mSend()), &chat, SLOT(sendMessage()));
    }else{
        qDebug() << "item is null";
    }
    
    return app.exec();