Access C++ function from QML
Solution 1
For any C++ code to be called from QML, it must reside inside a QObject
.
What you need to do is create a QObject
descended class with your function, register it to QML, instantiate it in your QML and call the function.
Note also that you have to mark your function with Q_INVOKABLE
.
Code:
#ifndef EIGEN_FUNCTION_HEADER_H
#define EIGEN_FUNCTION_HEADER_H
#include <QObject>
class MyObject : public QObject{
Q_OBJECT
public:
explicit MyObject (QObject* parent = 0) : QObject(parent) {}
Q_INVOKABLE int reken_tijden_uit(){
return 1;
}
};
#endif // EIGEN_FUNCTION_HEADER_H
main.cpp:
#include <QtGui/QApplication>
#include <QtDeclarative>
#include "qmlapplicationviewer.h"
#include "eigen_function_header.h"
Q_DECL_EXPORT int main(int argc, char *argv[])
{
QScopedPointer<QApplication> app(createApplication(argc, argv));
qmlRegisterType<MyObject>("com.myself", 1, 0, "MyObject");
QmlApplicationViewer viewer;
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
viewer.setMainQmlFile(QLatin1String("qml/tw_looptijden_berekenen/main.qml"));
viewer.showExpanded();
return app->exec();
}
QML:
import QtQuick 1.1
import com.myself 1.0
Rectangle {
width: 360
height: 360
Text {
text: qsTr("Hello World")
anchors.centerIn: parent
}
MyObject {
id: myobject
}
MouseArea {
anchors.fill: parent
onClicked: {
console.log(myobject.reken_tijden_uit())
}
}
}
Solution 2
As an alternative to qmlRegisterType() in main.cpp, you can also use context properties to make QObject variables available in QML. (In case you don't require to create different instances of your object with later QML).
Q_DECL_EXPORT int main(int argc, char *argv[])
{
QScopedPointer<QApplication> app(createApplication(argc, argv));
QmlApplicationViewer viewer;
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
viewer.setMainQmlFile(QLatin1String("qml/tw_looptijden_berekenen/main.qml"));
viewer.showExpanded();
// add single instance of your object to the QML context as a property
// the object will be available in QML with name "myObject"
MyObject* myObject = new MyObject();
viewer.engine()->rootContext()->setContextProperty("myObject", myObject);
return app->exec();
}
In QML, you can then access the object from anywhere in your code with the given name specified in main.cpp. No additional declarations required:
MouseArea {
anchors.fill: parent
onClicked: {
myObject.reken_tijden_uit()
}
}
You can find more information on QML<->C++ communication possibilities here: https://v-play.net/cross-platform-development/how-to-expose-a-qt-cpp-class-with-signals-and-slots-to-qml
![Mathlight](https://i.stack.imgur.com/zuqKa.jpg?s=256&g=1)
Mathlight
Updated on March 09, 2020Comments
-
Mathlight over 4 years
I'm trying to make a little program with Qt. I have a
main.cpp
with the following code:#include <QtGui/QApplication> #include "qmlapplicationviewer.h" Q_DECL_EXPORT int main(int argc, char *argv[]) { QScopedPointer<QApplication> app(createApplication(argc, argv)); QmlApplicationViewer viewer; viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer.setMainQmlFile(QLatin1String("qml/tw_looptijden_berekenen/main.qml")); viewer.showExpanded(); return app->exec(); } int reken_tijden_uit(){ return true; }
and I have a
.qml
file:import QtQuick 1.1 Rectangle { width: 360 height: 360 Text { text: qsTr("Hello World") anchors.centerIn: parent } MouseArea { anchors.fill: parent onClicked: { Qt.quit(); } } }
Now, when I click on the
MouseArea
, the program quits. What I want is that it calls the functionreken_tijden_uit
in themain.cpp
file.I've googled a lot, and searched on this site to. I've found a couple of answers, but I didn't get one working.
So what code do I put where so I can call the function
reken_tijden_uit
in C++?Thanks in advance.
The header file looks like this:
#ifndef EIGEN_FUNCTION_HEADER_H #define EIGEN_FUNCTION_HEADER_H class MyObject : public QObject{ Q_OBJECT public: explicit MyObject (QObject* parent = 0) : QObject(parent) {} Q_INVOKABLE int reken_tijden_uit(){ return 1; } }; #endif // EIGEN_FUNCTION_HEADER_H
main.cpp
:#include <QtGui/QApplication> #include "qmlapplicationviewer.h" #include "eigen_function_header.h" QScopedPointer<QApplication> app(createApplication(argc, argv)); qmlRegisterType<MyObject>("com.myself", 1, 0, "MyObject"); Q_DECL_EXPORT int main(int argc, char *argv[]) { QScopedPointer<QApplication> app(createApplication(argc, argv)); QmlApplicationViewer viewer; viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer.setMainQmlFile(QLatin1String("qml/tw_looptijden_berekenen/main.qml")); viewer.showExpanded(); return app->exec(); }
and the QML file:
import QtQuick 1.1 import com.myself 1.0 Rectangle { width: 360 height: 360 Text { text: qsTr("Hello World") anchors.centerIn: parent } MyObject { id: myobject } MouseArea { anchors.fill: parent onClicked: { myobject.reken_tijden_uit() } } }
And the errors are as follow:
D:\*\main.cpp:6: error: 'argc' was not declared in this scope D:\*\main.cpp:6: error: 'argv' was not declared in this scope D:\*\main.cpp:8: error: expected constructor, destructor, or type conversion before '<' token
So what did I do wrong?
-
Chris Browet over 12 yearsBest, in a separate .cpp/.h added to your project. Do not forget to include the .h in main.cpp before doing the qmlRegisterType
-
Mathlight over 12 yearsalright, i've got a couple of errors, i will post a new answer so it's clear y what the problem is...
-
Chris Browet over 12 years1) You have twice "QScopedPointer<QApplication>...". Remove the first one 2) Move "qmlRegisterType<MyObject>..." just after the second "QScopedPointer...", i.e. inside main{} 3) do a "console.log(myobject.reken_tijden_uit())" to check that it works (will appear in console in qt creator)
-
Chris Browet over 12 yearsIn the QML? I.e. onClicked: { console.debug(myobject.reken_tijden_uit()) }
-
Mathlight over 12 yearsalrght, i got still errors, and put the console.log on the onClicked in the qml. the errors are as follow: D:*\main.cpp:-1: In function 'int qMain(int, char**)': AND D:*\main.cpp:14: error: 'qmlRegisterType' was not declared in this scope AND D:*\main.cpp:14: error: expected primary-expression before '>' token
-
Mathlight over 12 yearsand 3 warnings.... 1); D:*\main.cpp:14: warning: left-hand operand of comma has no effect 2); D:*\main.cpp:14: warning: right-hand operand of comma has no effect 3);D:*\main.cpp:14: warning: right-hand operand of comma has no effect
-
Mathlight over 12 yearsalright, i think it's working now, because i've got now 15 errors (A) the first one is: D:\qt\tw_looptijden_berekenen\tw_looptijden_berekenen-build-desktop-Qt_4_8_0_for_Desktop_-_MinGW__Qt_SDK__Debug\debug\moc_eigen_function_header.cpp:12: error: #error "The header file 'eigen_function_header.h' doesn't include <QObject>."
-
Chris Browet over 12 yearsIndeed. Edited for #include <QObject>
-
Mathlight over 12 yearsyeeey :P srr, i thought i had it but didn't ;P it works now. Thanks for the help ;)
-
johnbakers over 10 yearsIf you instantiate it in QML, then how can you give this instance access to other objects you have in C++? For example, if an invokable function requires pointers to other objects in your C++ environment, you'd have to give the instance some way of accessing them. How?
-
KernelPanic almost 9 years@hellofunk why is function
main
declared asQ_DECL_EXPORT
? -
johnbakers almost 9 years@MarkoFrelih see this: stackoverflow.com/questions/13911387/… i can't remember the reasoning in this particular case, but i don't use Qt anymore and this was a couple years ago
-
Vincent Fourmond almost 7 yearsSome important caveat: the function marker with Q_INVOKABLE has to be public (or at least, not private, haven't checked for protected).
-
Mikolasan about 5 yearsThere is a [flowchart in Qt docs] (doc.qt.io/qt-5/…) that helps to decide when better to use qmlRegisterTypes approach and when setContextProperty