5

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.

MrEricSir
  • 8,044
  • 4
  • 30
  • 35
Alaa Salah
  • 1,047
  • 3
  • 12
  • 28
  • What are the errors that it gives? – lthreed Jul 21 '14 at 18:24
  • @lthreed Sorry budd, I've edited the question & added all necessary information. – Alaa Salah Jul 21 '14 at 21:02
  • Come on... you do not even mention which line gives the error, nor do you include your class... The error must be coming from _your_ class. – László Papp Jul 21 '14 at 22:03
  • Is MyClass based on QObject class? – Jairo Jul 22 '14 at 08:47
  • @Jairo Yup, that's it! myclass should inherit from QObject. But that also doesn't solve the main problem unfortunately .. How can I change the code to make it possible to use a C++ function ( `myClass.buttonClicked(QString)` ) from QML like: [ `_myClass.buttonClicked("JJJ")` ]? Thanks :) – Alaa Salah Jul 22 '14 at 14:57
  • @FinalContest I want someone to assist me migrating from `QQmlApplicationEngine` to `QDeclarativeView` or `QtQuickView` to achieve the main goal ( using a C++ function when a QML button is clicked ). :) – Alaa Salah Jul 22 '14 at 15:02
  • @hyde Oh sorry, I wrote the question with (myClass) alias to make it easier for other people to give a generalized solution. Edited – Alaa Salah Jul 22 '14 at 15:16
  • No problem. However, the question is still missing what error you are getting. Since there are no answers for your current code to make invalid, you might as well update the code to the latest version (with `Q_OBJECT` etc), explain what is wrong with it (eg. what exact error message you get). – hyde Jul 22 '14 at 15:22
  • @hyde Everything is written in the question now :] – Alaa Salah Jul 22 '14 at 16:57
  • @hyde Actually no, `_` is okay, as I've seen a lot of people use it. But to be sure, I've removed it & tried .. Not working, same error message **myClass** is not defined. – Alaa Salah Jul 22 '14 at 22:39

1 Answers1

11

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)
{
}
MrEricSir
  • 8,044
  • 4
  • 30
  • 35
  • 4
    In fact, you don't have to attach Q_INVOKABLE to slots. All slots are processed as invokable function by moc automatically. – slyx Jul 23 '14 at 04:40
  • @xylosper I didn't know that, but a quick experiment proves that you're right. I'll update my answer. Thanks for the correction and info! – MrEricSir Jul 23 '14 at 05:53
  • About the last point about constructor, for completeness: A good catch and a nasty surprise for future if not fixed, though not related to the problem in this question (here constructor is called with no arguments). – hyde Jul 23 '14 at 07:23
  • QQmlApplicationEngine works perfectly fine in my apps. I'm not sure what _audGrabber is, you didn't include that part of your QML in the question. – MrEricSir Jul 23 '14 at 17:08
  • Sorry, it works fine. Just had to remove `void buttonClicked();` to make it work, I think QML doesn't recognise this type of function declaring. Thank you so much. – Alaa Salah Jul 23 '14 at 23:13