Alaa Elrifaie Alaa Elrifaie - 22 days ago 9
C++ Question

Qt - How to run a C++ function when QML button is clicked? Using QQmlApplicationEngine

myclass.h

#ifndef MYCLASS_H
#define MYCLASS_H

#include <QDebug>
#include <QObject>

class MyClass : public QObject
{
public:
MyClass();

public slots:
void buttonClicked();
void buttonClicked(QString &in);
};

#endif // MYCLASS_H





myclass.cpp

#include "myclass.h"

MyClass::MyClass()
{
}

void MyClass::buttonClicked()
{
// Do Something
}

void MyClass::buttonClicked(QString &in)
{
qDebug() << in;
}





main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>
#include <myclass.h>
#include <QQmlContext>

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

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

MyClass myClass; // A class containing my functions

// Trying to "SetContextProperty" as I saw people do it to achieve C++/QML connection
QQmlContext * context = new QQmlContext(engine.rootContext());
context->setContextProperty("_myClass", &myClass);

return app.exec();
}


I want to use a function in myClass class which takes a QString parameter when a QML button is clicked ..

When I compile & run .. it all goes smoothly.
But when I click on the button .. it shows this error in the debugger:


qrc:///main.qml:80: ReferenceError: _myClass is not defined


~> "Line 80 in my QML file":

74: MouseArea {
75: id: mouseArea1
76: anchors.fill: parent
77: hoverEnabled: true;
78: onEntered: { rectangle1.border.width = 2 }
79: onExited: { rectangle1.border.width = 1 }
80: onClicked: _myClass.buttonClicked("Worked?")
81: }





EDIT: ( As for the error caused the compiling error )

As @Jairo suggested, all classes must be inherited from QObject.

Still looking for a solution to my main problem.

Answer

Uh oh. There's several things wrong here. (Does the code even compile?)

First things first. When passing something to the QML engine's root property, you can't create a new context -- you have to use the root context directly, like so:

engine.rootContext()->setContextProperty("_myClass", &myClass);

Next, the class definition has some problems. See my comments in the code below:

class MyClass : public QObject
{
    // This macro is required for QObject support.  You should get a compiler
    // error if you don't include this.
    Q_OBJECT

public:
    // QObjects are expected to support a parent/child hierarchy.  I've modified
    // the constructor to match the standard.
    explicit MyClass(QObject *parent = 0);

public slots:
    // This method needs to take either a QString or a const reference to one.
    // (QML doesn't support returning values via the parameter list.)
    void buttonClicked(const QString& in);
};

The constructor's implementation should pass the parent on to the base class:

MyClass::MyClass(QObject *parent) :
    QObject(parent)
{
}
Comments