" Error : Cannot assign [undefined] to QString " while communicating between C++ and QML



  • Hi !

    I have a QML code whom I am trying to communicate with with a C++ code.
    i have especially some shared object accessed from the QML by :

    testText.text=anchor.message
    

    but when doing this, an error is printed in the console:
    Error: Cannot assign [undefined] to QString
    here is the c++ code of my Anchor class, from QObject

    //Anchor.h
    class Anchor :public QObject
    {
    	Q_OBJECT
    	Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
    public:
    	Anchor();
    	Q_INVOKABLE void clicked(/*const QString& clickedStr*/);
    	Q_INVOKABLE int getVal(void);
    
    	QString message(void);
    	void setMessage(QString);
    
    signals:
    	void signalAnchor(QString s);
    	void messageChanged();
    
    public slots:
    	void slotAnchor(QString s);
    private :
    	QString msg;
    };
    
    #include "Anchor.h"
    
    Anchor::Anchor() :msg("I'm da QString m8")
    {
    	TRACE_DEBUG("Construction de l'Anchor ")
    		if(msg!=nullptr) printQStr(msg)//it works and print the string in the console
    }
    
    Q_INVOKABLE void Anchor::clicked(/*const QString& clickedStr*/)
    {
    	qDebug("Méthode invocable appelee sur click");
    }
    
    void Anchor::slotAnchor(QString s)
    {
    	static int i = 0;
    	s.append(" ").append(QString::number(++i));
    	qDebug() << "qDebug  : " << s;
    	emit signalAnchor(s);
    }
    
    Q_INVOKABLE int Anchor::getVal(void)
    {
    	return 124;
    }
    
    QString Anchor::message(void)
    {
    	printf("getMessage\n");
    	return msg;
    }
    void Anchor::setMessage(QString str)
    {
    	msg = str;
    	emit Anchor::messageChanged();
    }
    
    void Anchor::messageChanged(void) {
    	printf("messageChanged\n");
    }
    

    here is the test functions called in the main:

    QGuiApplication app(ai_argc, aipp_argv);
    
    	QQmlApplicationEngine engine;
    	engine.addImportPath(QStringLiteral("..\\..\\..\\..\\Tools\\Qt\\5.12.0\\x64\\5.12.0\\msvc2017_64\\qml"));
    	Anchor anchor;
    	QString  strCppQml = "transmission de chaine du C++ au QML reussie", strQmlCpp = "transmission de chaine du QML au C++ reussie";
    	anchor.setProperty("strQmlCpp", strQmlCpp);
    	engine.rootContext()->setContextProperty("strCppQml", strCppQml);
    //until now, everythin worked. The problem comes from the anchor, from the Q_PROPERTY
    	engine.rootContext()->setContextProperty("anchor", &anchor);
    	engine.load(QUrl(QML_TEST1_PATH));//the path is correct
    
    	return app.exec();
    

    So i am sure that the QString I'm trying to send is not empty. the object exists
    now, the QML

    import QtQuick 2.5
    import QtQuick.Window 2.5
    import "\Items" as Koala
    //import "../../Anchor"
    
    Window{
        property var value: anchor.getVal();
        visible: true
        id:mainWindow
        width: 150; height: 150
        color: "#000000"
    
        Connections{
            target: anchor
            onSignalAnchor:{
                signalText.text=s
                signalText.x=signalText.x+5;
            }
        }
        Text{
           id: testText
           color: "#ffffff"
           text: anchor.message
           anchors.centerIn: parent
           font.pointSize: 10
           visible: false
        }
        Text {
            id: signalText
            x: 27
            y: 102
            color: "#f0f0f0"
            width: 60
            height: 14
            font.pixelSize: 12
        }
        MouseArea{
            anchors.fill: parent
    
            onClicked:
            {
                anchor.clicked();
                testText.text=anchor.message//there it is!
                testText.visible=true;
                mainWindow.setGeometry(1200,330,500,400)
                signalText.text= value;
            }
            onDoubleClicked: anchor.slotAnchor("calling slotAnchor")
        }
    }
    

    Do you know where does that error comes from ? how can I fix it and FINALLY set an efficient communication ?
    Thanks for reading



  • This is an immediate problem:

    void Anchor::messageChanged(void) {
    	printf("messageChanged\n");
    }
    

    You've provided a definition for the signal. I don't know how you got it to compile because I couldn't.
    Once I fixed that the code ran as I suppose it's supposed to.



  • @mranger90 you're right, that's stupid.

    I changed it in an empty definition

    void Anchor::messageChanged(void) {}
    

    but I have the error anyway.
    I think I tried everything now. using qmlRegisterType to import my type, a Q_INVOKABLE method, using the Q_PROPERTY.
    In every case, i have this error : cannot assign [undefined] to type
    I tried with double, int, QString...



  • No, the point is that you have it defined at all. Signals should never have a body.



  • @Quentin91
    hey did you try marking your qml strings with "qsTr()" ?
    could you try qsTr(anchor.message)?

    Also, you can't define signals as mentioned by @mranger90 as it's already defined in moc code. You will get error as multiple definition of the signal function.
    Thanks.



  • @Ronak5 no, I didn't. that's probably not the problem any current test is trying to share a bool with QML and the problem is the same. but I'll remember to try it when sharing a string :)

    So here is a simpler project and use a Singleton. One of the problem was that I have to declare my object in the QML when using qmlRegisterType. And I don't want to. So here is the new code, the error is the same.
    I followed the example of the doc here https://doc.qt.io/qt-5/qtqml-cppintegration-definetypes.html

    miniModel.h (the singleton)

    #ifndef _MINIMODEL_H_
    #define _MINIMODEL_H_
    #include <stdlib.h>
    #include <stdio.h>
    #include <iostream>
    #include <string>
    #include <QtGui/qguiapplication.h> 
    #include <QtQml/qqmlcontext.h>
    #include <QtQml/qqmlapplicationengine.h>
    #include <QtCore/qdebug.h>
    #include <QtCore/qobject.h>
    #include <QtCore/qvariant.h>
    class MiniModel : public QObject
    {
    	Q_OBJECT
    	Q_PROPERTY(bool miniboule READ miniboule WRITE setMiniboule NOTIFY minibouleChanged)
    public:
    	MiniModel();
    	bool miniboule();
    	void setMiniboule(bool bouboule);
    signals:
    	void minibouleChanged();
    private:
    	bool m_miniboule;
    };
    #endif
    

    main.cpp v1 : singleton using a QObject

    #include "miniModel.h"
    
    //defining a miniModel instance as a singleton
    static QObject* mp_singleton(QQmlEngine* engine, QJSEngine* scriptEngine)
    {
    	Q_UNUSED(engine)
    	Q_UNUSED(scriptEngine)
    
    	MiniModel* miniSingleton = new MiniModel();
    	return miniSingleton;
    }
    
    int main(int argc=0, char* argv[]=nullptr)
    {
    	printf("\n launching \n");
    	QGuiApplication app(argc, argv);
    
    	qmlRegisterSingletonType<MiniModel>("myModel.miniModel", 1, 0, "MiniModel",mp_singleton);
    
    	QQmlApplicationEngine engine;
    
    	engine.addImportPath(QStringLiteral("..\\..\\..\\..\\Tools\\Qt\\5.12.0\\x64\\5.12.0\\msvc2017_64\\qml"));
    	engine.load(QUrl(QStringLiteral("..\\..\\..\\miniModel.qml")));
    
    	return app.exec();
    }
    

    main.cpp v2 : singletin using QJSValue

    #include "miniModel.h"
    
    static QJSValue m_singletonModel(QQmlEngine* engine, QJSEngine* scriptEngine) {
    	Q_UNUSED(engine)
    
    	static bool m_miniboule;
    	QJSValue miniModel = scriptEngine->newObject();
    	miniModel.setProperty("miniboule", m_miniboule);
    	return miniModel;
    }
    
    int main(int argc = 0, char* argv[] = nullptr)
    {
    	printf("\n launching \n");
    	QGuiApplication app(argc, argv);
    
    	qmlRegisterSingletonType("myModel.miniModel", 1, 0, "MiniModel", m_singletonModel);
    
    	QQmlApplicationEngine engine;
    
    	engine.addImportPath(QStringLiteral("..\\..\\..\\..\\Tools\\Qt\\5.12.0\\x64\\5.12.0\\msvc2017_64\\qml"));
    	engine.load(QUrl(QStringLiteral("..\\..\\..\\miniModel.qml")));
    
    	return app.exec();
    }
    
    

    and the QML. be careful, it's tough

    import QtQuick 2.5
    import QtQuick.Window 2.5
    import QtQuick.Controls 1.4
    
    import myModel.miniModel 1.0 as MyModel
    ApplicationWindow {
        id: root
        width: 300
        height: 480
        visible:true
        Text{
           id: textTest
           x: 62
           y: 75
           color: "#d21616"
           text:  "vanilla"
           visible: false//the text is supposed to appear when clicking in the mouseArea
        }
        MouseArea{
            anchors.fill: parent
            onClicked: textTest.visible=  MyModel.Minimodel.miniboule//the boolean I want to acess, defined to true
        }
    }
    

    now, the error changed, since I called MyModel.MiniModel.miniboule instead of just MiniModel.miniboule
    the error is TypeError: Cannot read property 'miniboule' of undefined


Log in to reply
 

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