Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 347
Alaa Salah Avatar asked Jul 21 '14 17:07

Alaa Salah


1 Answers

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)
{
}
like image 145
MrEricSir Avatar answered Sep 28 '22 04:09

MrEricSir