admin管理员组文章数量:1312879
I've started learning QML
recently (after trying it out a long time ago) and I'm stuck at the way Qt
C++
code interacts with QML
and vice versa.
I have a Counter
which has the following header:
#include <QObject>
#include <QTimer>
class Counter : public QObject
{
Q_OBJECT
Q_PROPERTY(int count
READ getCount
WRITE setCount
NOTIFY signalCountChanged)
public:
Counter(QObject *parent = Q_NULLPTR);
int getCount();
void setCount(int count);
signals:
void signalCountChanged(int);
public slots:
void slotStart();
private slots:
void slotTimeout();
private:
int count;
QTimer *timer;
};
My main.cpp
is as follows:
#include <QtGui/QGuiApplication>
#include <QtQml/QQmlContext>
#include <QtGui/QGuiApplication>
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickView>
#include "counter.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<Counter>("org.qmlplayground.counter", 0, 1, "Counter");
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
QObject *viewO = dynamic_cast<QObject*>(view.rootObject());
Counter c;
// Register Counter instance as "counter" property of top level context so that it can be accessed from within the QML code (for example: set the value count)
view.rootContext()->setContextProperty("counter", &c);
QObject::connect(viewO, SIGNAL(signalStartCounter()),
&c, SLOT(slotStart()));
QObject::connect(viewO, SIGNAL(signalQuit()), &app, SLOT(quit()));
view.show();
return app.exec();
}
and finally part of my QML
(the main.qml
which is loaded in the QQuickView
while the rest being an UI form):
import QtQuick 2.7
import QtQuick.Window 2.2
// Importing some JavaScript files
import "qrc:/loggingFunctions.js" as LOG
import "qrc:/parseFunctions.js" as PARSE
// Importing a Qt C++ custom module
import org.qmlplayground.counter 0.1
MainForm {
property int countState: counter.count // ERROR HERE
signal signalStartCounter()
signal signalQuit()
anchors.fill: parent
textInputMouseArea.onClicked: {
LOG.logger("Clicked! Selecting all text in text input field", "N")
textInput.selectAll()
}
textInput.onAccepted: {
if(textInput.text === "quit") signalQuit()//Qt.quit();
if(textInput.text === "help") textInput.text = LOG.logger("Displaying help", "H");
var res = PARSE.parseInput(textInput.text);
if(res && (typeof res === 'object') && res.constructor === Array) {
switch(res[0]) {
case "fact":
labelOutput.text = res[1];
break;
case "count":
counter.count = res[1];
signalStartCounter();
break;
}
}
}
onCountStateChanged:
console.log("Hello")
textInput.onTextChanged:
console.log("Text changed");
}
As you can see I've already tested two signals sent from my QML
to my C++
code one being connected to my QGuiApplication
's slot quit()
and the other being connected to my counter
's slot slotStart()
. It works fine. It seems that the line
counter.count = res[1];
doesn't cause any issues (perhaps because it's JS
and not QML
?). Now I want to read the count
value of my Counter
instance and update my UI accordingly. If I'm not mistaken every QML
property automatically gets a couple of things one of these being the onChanged
method (event handler or whatever it's called).
When I run my code however I get
`qrc:/main.qml:21: ReferenceError: counter is not defined
I thought that doing view->rootContext()->setContextProperty("counter", &c);
would be enough but it seems that I'm missing something. So the more general question would be how do I properly make a C++
object visible in QML
context.
I've started learning QML
recently (after trying it out a long time ago) and I'm stuck at the way Qt
C++
code interacts with QML
and vice versa.
I have a Counter
which has the following header:
#include <QObject>
#include <QTimer>
class Counter : public QObject
{
Q_OBJECT
Q_PROPERTY(int count
READ getCount
WRITE setCount
NOTIFY signalCountChanged)
public:
Counter(QObject *parent = Q_NULLPTR);
int getCount();
void setCount(int count);
signals:
void signalCountChanged(int);
public slots:
void slotStart();
private slots:
void slotTimeout();
private:
int count;
QTimer *timer;
};
My main.cpp
is as follows:
#include <QtGui/QGuiApplication>
#include <QtQml/QQmlContext>
#include <QtGui/QGuiApplication>
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickView>
#include "counter.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<Counter>("org.qmlplayground.counter", 0, 1, "Counter");
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
QObject *viewO = dynamic_cast<QObject*>(view.rootObject());
Counter c;
// Register Counter instance as "counter" property of top level context so that it can be accessed from within the QML code (for example: set the value count)
view.rootContext()->setContextProperty("counter", &c);
QObject::connect(viewO, SIGNAL(signalStartCounter()),
&c, SLOT(slotStart()));
QObject::connect(viewO, SIGNAL(signalQuit()), &app, SLOT(quit()));
view.show();
return app.exec();
}
and finally part of my QML
(the main.qml
which is loaded in the QQuickView
while the rest being an UI form):
import QtQuick 2.7
import QtQuick.Window 2.2
// Importing some JavaScript files
import "qrc:/loggingFunctions.js" as LOG
import "qrc:/parseFunctions.js" as PARSE
// Importing a Qt C++ custom module
import org.qmlplayground.counter 0.1
MainForm {
property int countState: counter.count // ERROR HERE
signal signalStartCounter()
signal signalQuit()
anchors.fill: parent
textInputMouseArea.onClicked: {
LOG.logger("Clicked! Selecting all text in text input field", "N")
textInput.selectAll()
}
textInput.onAccepted: {
if(textInput.text === "quit") signalQuit()//Qt.quit();
if(textInput.text === "help") textInput.text = LOG.logger("Displaying help", "H");
var res = PARSE.parseInput(textInput.text);
if(res && (typeof res === 'object') && res.constructor === Array) {
switch(res[0]) {
case "fact":
labelOutput.text = res[1];
break;
case "count":
counter.count = res[1];
signalStartCounter();
break;
}
}
}
onCountStateChanged:
console.log("Hello")
textInput.onTextChanged:
console.log("Text changed");
}
As you can see I've already tested two signals sent from my QML
to my C++
code one being connected to my QGuiApplication
's slot quit()
and the other being connected to my counter
's slot slotStart()
. It works fine. It seems that the line
counter.count = res[1];
doesn't cause any issues (perhaps because it's JS
and not QML
?). Now I want to read the count
value of my Counter
instance and update my UI accordingly. If I'm not mistaken every QML
property automatically gets a couple of things one of these being the onChanged
method (event handler or whatever it's called).
When I run my code however I get
`qrc:/main.qml:21: ReferenceError: counter is not defined
I thought that doing view->rootContext()->setContextProperty("counter", &c);
would be enough but it seems that I'm missing something. So the more general question would be how do I properly make a C++
object visible in QML
context.
1 Answer
Reset to default 12This took me perhaps 2 hours to figure out (I posted my question when I was on the verge of miting a suicide :D) but the answer was really obvious: how can I call for a property which hasn't been initialized yet? The solution to my problem is basically to move the setContextProperty()
BEFORE I load the QML
file:
// ...
QQuickView view;
Counter c;
view.rootContext()->setContextProperty("counter", &c);
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
// ...
By doing so the property is first added to the root context of the view
and after that the additional QML
stuff is loaded but the counter
property is still present). With the previous version of my code I was basically trying to access counter
inside my QML
file BEFORE I have added it as a property.
本文标签: javascriptQML reports ReferenceError XYZ is not defined on C object added to contextStack Overflow
版权声明:本文标题:javascript - QML reports ReferenceError: XYZ is not defined on C++ object added to context - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741904755a2404077.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论