Connecting Signal QML to C++ (Qt5)

2.6k views Asked by At

I would like to change a the color of a rectangle when I click a button. They are both in the main.qml file. I'd like to send a signal to C++ backend to change the color of the rectangle. I can't seem to figure it out from the code given in the documentation

main.qml: import QtQuick 2.4 import QtQuick.Controls 1.3 import QtQuick.Window 2.2 import QtQuick.Dialogs 1.2

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


    id:root

    signal mysignal()


    Rectangle{
     anchors.left: parent.left
     anchors.top: parent.top
     height : 100
     width : 100
    }

    Button
    {

        id: mybutton
        anchors.right:parent.right
        anchors.top:parent.top
        height: 30
        width: 50
     onClicked:root.mysignal()

    }

}

main.cpp:

#include <QApplication>
#include <QQmlApplicationEngine>
#include<QtDebug>
#include <QQuickView>

class MyClass : public QObject
{
    Q_OBJECT
public slots:
    void cppSlot() {
        qDebug() << "Called the C++ slot with message:";
    }
};

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

  MyClass myClass;

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

    QPushButton *mybutton = engine.findChild("mybutton");

    engine.connect(mybutton, SIGNAL(mySignal()),
                   &myClass, SLOT(cppSlot()));

    return app.exec();
}

Any help would be appreciated!

2

There are 2 answers

1
peppe On
QPushButton *mybutton = engine.findChild("mybutton");

First, QObject::findChild finds QObjects by object name, not id (which is local to a context anyhow). Hence in QML you need something like:

objectName: "mybutton"

Second, I think you need to perform that findChild not on the engine itself, but on its root objects as returned from QQmlApplicationEngine::rootObjects().

// assuming there IS a first child
engine.rootObjects().at(0)->findChild<QObject*>("myButton"); 

Third, a Button in QML is represented by a type that you don't have available in C++. So you can't just assign the result to a QPushButton *, but you need to stick with the generic QObject *.

0
user3927312 On

I had to create a seperate class and header file and then connect it to the signal in main.cpp

main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>
#include<QtDebug>
#include <QQuickView>
#include<QPushButton>
#include<myclass.h>


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



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

    QObject *topLevel = engine.rootObjects().at(0);

    QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);

    MyClass myClass;

    QObject::connect(window,
                     SIGNAL(mysignal()),
                     &myClass,
                     SLOT(cppSlot())
                     );


    return app.exec();
}

myclass.h

#ifndef MYCLASS
#define MYCLASS



#include <QObject>
#include <QDebug>

class MyClass : public QObject
{
    Q_OBJECT

public slots:
    void cppSlot();

};
#endif // MYCLASS

myclass.cpp

#include<myclass.h>

void MyClass::cppSlot(){

    qDebug()<<"Trying";
}