Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

[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