" 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 QMLimport 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... -
@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.htmlminiModel.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