QML reports ReferenceError: XYZ is not defined on C++ object added to context
QML reports ReferenceError: XYZ is not defined on C++ object added to context
我最近开始学习 QML
(在很久以前尝试过之后),但我一直停留在 Qt
C++
代码与 [=15 交互的方式=] 反之亦然。
我有一个 Counter
,其中包含以下 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;
};
我的main.cpp
如下:
#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();
}
最后是我的 QML
的一部分(main.qml
加载到 QQuickView
中,其余部分是 UI 形式):
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");
}
如你所见,我已经测试了从我的 QML
发送到我的 C++
代码的两个信号,一个连接到我的 QGuiApplication
的插槽 quit()
另一个连接到我的 counter
的插槽 slotStart()
。它工作正常。似乎行
counter.count = res[1];
不会导致任何问题(可能是因为它是 JS
而不是 QML
?)。现在我想读取我的 Counter
实例的 count
值并相应地更新我的 UI 。如果我没记错的话,每个 QML
属性 都会自动得到一些东西,其中之一是 onChanged
方法(事件处理程序或它所调用的任何东西)。
当我 运行 我的代码时,我得到
`qrc:/main.qml:21: ReferenceError: counter is not defined
我认为 view->rootContext()->setContextProperty("counter", &c);
就足够了,但似乎我遗漏了什么。所以更普遍的问题是我如何 正确地 使 C++
object 在 QML
上下文中可见。
这大概花了我 2 个小时才弄清楚(我在濒临自杀的时候发布了我的问题 :D)但答案非常明显:我怎样才能要求 属性哪个还没有初始化?我的问题的解决方案基本上是移动 setContextProperty()
BEFORE 我加载 QML
文件:
// ...
QQuickView view;
Counter c;
view.rootContext()->setContextProperty("counter", &c);
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
// ...
通过这样做,属性 首先被添加到 view
的根上下文中,然后加载额外的 QML
内容,但 counter
属性 仍然存在)。使用我以前版本的代码,我基本上是在 QML
文件 中访问 counter
,然后 我将其添加为 属性。
我最近开始学习 QML
(在很久以前尝试过之后),但我一直停留在 Qt
C++
代码与 [=15 交互的方式=] 反之亦然。
我有一个 Counter
,其中包含以下 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;
};
我的main.cpp
如下:
#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();
}
最后是我的 QML
的一部分(main.qml
加载到 QQuickView
中,其余部分是 UI 形式):
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");
}
如你所见,我已经测试了从我的 QML
发送到我的 C++
代码的两个信号,一个连接到我的 QGuiApplication
的插槽 quit()
另一个连接到我的 counter
的插槽 slotStart()
。它工作正常。似乎行
counter.count = res[1];
不会导致任何问题(可能是因为它是 JS
而不是 QML
?)。现在我想读取我的 Counter
实例的 count
值并相应地更新我的 UI 。如果我没记错的话,每个 QML
属性 都会自动得到一些东西,其中之一是 onChanged
方法(事件处理程序或它所调用的任何东西)。
当我 运行 我的代码时,我得到
`qrc:/main.qml:21: ReferenceError: counter is not defined
我认为 view->rootContext()->setContextProperty("counter", &c);
就足够了,但似乎我遗漏了什么。所以更普遍的问题是我如何 正确地 使 C++
object 在 QML
上下文中可见。
这大概花了我 2 个小时才弄清楚(我在濒临自杀的时候发布了我的问题 :D)但答案非常明显:我怎样才能要求 属性哪个还没有初始化?我的问题的解决方案基本上是移动 setContextProperty()
BEFORE 我加载 QML
文件:
// ...
QQuickView view;
Counter c;
view.rootContext()->setContextProperty("counter", &c);
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
// ...
通过这样做,属性 首先被添加到 view
的根上下文中,然后加载额外的 QML
内容,但 counter
属性 仍然存在)。使用我以前版本的代码,我基本上是在 QML
文件 中访问 counter
,然后 我将其添加为 属性。