QML and C++ Integration [solved]



  • Hello,

    I have gotten communication from c++ and QML using the Q_PROPERTY macro with basic types such as QString and int, but I cannot get it to work with my own custom class that extends QObject. Here is my Code:

    //simple.h
    @#include <QObject>
    #include <QMetaType>

    class Simple : public QObject
    {
    Q_Object
    Q_PROPERTY(int hour READ getHour WRITE setHour NOTIFY hourChanged)

    public:
    explicit Simple(QObject *parent = 0);
    int getHour();
    void setHour(int hour);

    signals:
    void hourChanged(int);

    private:
    int _hour;
    };

    Q_DECLARE_METATYPE(Simple*)
    @

    //simple.cpp
    @#include "simple.h"

    Simple::Simple(QObject *parent)
    : QObject(parent)
    {
    _hour = 129;
    }

    int Simple::getHour() {
    return _hour;
    }

    void Simple::setHour(int hour) {
    _hour = hour;
    emit hourChanged(_hour);
    }
    @

    //step.h
    @#include <QObject>
    #include <QMetaType>
    #include "simple.h"

    class Step : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(Simple* sim READ getSim)

    public:
    explicit Step(QObject parent = 0);
    Simple
    getSim();

    private:
    Simple* _sim;
    };
    @

    //step.cpp
    @#include "step.h"

    Step::Step(QObject parent)
    : QObject(parent)
    {
    qRegisterMetaType<Simple
    >("Simple");
    _sim = new Simple();
    }

    Simple* Step::getSim() {
    return _sim;
    }
    @

    //main.cpp
    @#include <QtGui/QGuiApplication>
    #include "qtquick2applicationviewer.h"
    #include <QQmlContext>
    #include "step.h"

    int main(int argc, char *argv[])
    {
    QGuiApplication app(argc, argv);
    QtQuick2ApplicationViewer viewer;

     Step step;
     viewer.rootContext()->setContextProperty("step", &step);
    
     viewer.setMainQmlFile&#40;QStringLiteral("qml/Cineflux_001/main.qml"&#41;&#41;;
     viewer.showExpanded(&#41;;
     return app.exec(&#41;;
    

    }
    @

    //main.qml
    @import QtQuick 2.0

    Rectangle {
    width: 200; height: 200;

     Component.onCompleted: {
          console.log(step.sim&#41;; //prints QVariant(Simple*&#41;
          console.log(step.sim.hour) //prints undefined
     }
    

    }
    @

    I do not understand why step.min prints the object, but when I try and access the hour property it gives me undefined. Is this because the c++ object is a pointer? I am not sure. I have fiddled with this a lot and I either get META compile errors or undefined. Please help me.

    Thank you



  • Hello. First of all, at the class declaration of Simple, i suppose you mean that the base object is QObject not Simple, right?

    So for your problem. With the following changes it worked for me, though i dont know if there is a better/cleaner way:

    In Simple.h remove the
    @
    Q_DECLARE_METATYPE(Simple*)
    @

    In main.cpp add:
    @
    qmlRegisterType<Simple>("CustomObjects", 1, 0, "Simple");
    @

    In main.qml add:
    @
    import CustomObjects 1.0
    @

    Now try and see what happends :P

    PS: a final info. The following Q_DECLARE_METATYPE(Simple*) doen't work for you because you are registering just a pointer, not the class it self. So for it to work you should use it as follows:
    @
    Q_DECLARE_METATYPE(Simple)
    @

    But in that case you need to create copy constructor, overload the operator= and implement a destructor. I have tried it and it didn't work at the first round, may be you will be more lucky. Oh and if you try it, don't forget to add somewhere the line:
    @
    qRegisterMetaType<Simple>("Simple");
    @

    Regards!



  • Yes, the class declaration was a typo ;/

    I do not want to initialize the c++ object in QML, rather I just want to access it. So the qmlRegisterType will not work.

    I tried overloading the =operator, without any luck. According to this it is not possible:

    http://qt-project.org/doc/qt-4.8/object.html#qt-objects-identity-vs-value

    I get a couple compile time errors notably:
    error: 'QObject::QObject(const QObject&)' is private
    synthesized method 'Simple::Simple(const Simple&)' first required here

    Any other thoughts?

    Thank you for your help.



  • The qmlRegisterType is not needed in your limited case; its useful to have it when you use the Q_ENUMS macro, though.



  • Maybe you can try changing
    Q_PROPERTY(Simple* sim READ getSim)
    to
    Q_PROPERTY(QObject* sim READ getSim)

    you should be able to leave the rest as is.



  • Thank you very much Thomas. That sure did the trick. You rock!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.