问题
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:
This took me perhaps 2 hours to figure out (I posted my question when I was on the verge of commiting 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.
来源:https://stackoverflow.com/questions/38499869/qml-reports-referenceerror-xyz-is-not-defined-on-c-object-added-to-context