[SOLVED]"TypeError: Object [object Object] has no method" w/ qmlRegisterType



  • I'm pretty certain this is the correct thread to post this in. First let me say, I'm very new to QT and QML, I've been working on an app in C and GTK, but for various reasons decided to switch to QML, figuring out how to combine C and C++ was easy enough, what I've had the most difficulty with is creating my Makefile, however after a few days I've gotten that all figured out (I didn't want to use qmake, so I figured out how to manually do a Makefile), my program compiles fine, and my QML gui shows, however when using qmlRegisterType I can't call methods from C++ in QML.

    Ok, here is my gui.h:
    @#ifdef __cplusplus
    #include <QGuiApplication>
    #include <QQuickView>
    #include <QtQml>

    class QmlConnect : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString* getData READ getData)

    public:
    QmlConnect() {

    }
    Q_INVOKABLE QString* getData() {
    static QString data_list[] = {"Data1", "Data2", "Data3", "Data4"};
    return data_list;
    }
    };
    #endif

    #ifdef __cplusplus
    extern "C" {
    #endif
    void gui_Init(int argc, char **argv);
    #ifdef __cplusplus
    }
    #endif@

    Here is my gui.cpp:
    @#include "gui.h"

    extern "C" {
    #include "../globalvars.h"
    #include "../library.h"
    #include "../config.h"
    #include "../misc.h"
    }

    void gui_Init(int argc, char **argv) {
    QGuiApplication q_app(argc, argv);

    // Connect QT C++ to QML
    qmlRegisterType<QmlConnect>("QmlConnect", 1, 0, "QmlConnect");

    // Start QML app
    QQuickView view;
    view.setSource(QUrl::fromLocalFile("gui.qml"));
    view.show();

    q_app.exec();
    }@

    And here's my gui.qml file:
    @import QtQuick 2.0
    import Ubuntu.Components 0.1
    import Ubuntu.Components.ListItems 0.1 as ListItem

    import QmlConnect 1.0

    MainView {
    objectName: "mainView"
    applicationName: "MyApp"
    id: root

    width: units.gu(100)
    height: units.gu(80)

    property real margins: units.gu(2)
    property real buttonWidth: units.gu(9)

    Column {
    id: libraryColumn
    ListItem.Header {text: "Library"}
    ListItem.Standard {text: "Section1"}
    ListItem.Standard {text: "Section2"}
    ListItem.Divider {}
    ListItem.Header {text: "Lists"}

    width: units.gu(10)
    anchors {
    left: parent.left
    top: parent.top
    bottom: parent.bottom
    }
    }
    Grid {
    Component.onCompleted: {
    var data = QmlConnect.getData();
    for(var i = 0; i < data.length; i++) {
    console.log(data[i]);
    }
    }
    }
    }@

    Now what's happening is when my QML file tries to call QmlConnect.getData() it throws the error "TypeError: Object [object Object] has no method 'getData'"

    It doesn't fail to import the class itself, but it can't seem to call the mothod from the class. Any help is greately apprecieated.



  • Hi,

    A couple of issues: your QmlConnect type isn't registered as a singleton type, so you need to instantiate an instance of it, in order to invoke a member function.

    @
    MainView {
    id: root

    QmlConnect {
        id: qmlconnect
    }
    
    // ....
    
    Grid {
        Component.onCompleted: {
            var data = qmlconnect.getData()
            // ...
        }
    }
    

    }
    @

    Secondly, return a QStringList instead of a QString*. The overhead of passing core types by value is very low, as they use copy-on-write implicit sharing, and QML doesn't support returning (or interacting with) pointers unless they're QObject* (or QObject-derived*) - except wrapped in QVariants at which point they're opaque to QML anyway.

    You can also use a Q_PROPERTY instead of a Q_INVOKABLE to be more declarative:

    @
    class QmlConnect : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(QStringList stringArray READ stringArray CONSTANT)

    public:
    QmlConnect(QObject *parent = 0);
    ~QmlConnect();

    QStringList stringArray() const { QStringList retn; retn << "one" << "two" << "three"; return retn; }
    

    };
    @

    Then in the qml, instead of calling getData() just resolve stringArray:

    @
    Component.onCompleted: {
    var data = qmlconnect.stringArray
    // ....
    }
    @

    Cheers,
    Chris.



  • Your amazing!!! Thank you, now I can move on with my project :D See I'm not even that familiar with C++, I don't even know what a singleton is :P Luckily the amount of C++ going into this will be minimal it's just to get variables from my C functions and pass them along to the QML, and vice versa.

    Is there a way to vote up replies? Or mark them as "Answers"? Like on other forums.


Log in to reply
 

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