Access C++ Function from Qml

Access C++ function from QML

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())
}
}
}

How to call c++ function from qml and change the lable text

You can find the documentation for integrating C++ and QML here: http://developer.blackberry.com/cascades/documentation/dev/integrating_cpp_qml/

As a cliff's notes:

In your HelloBB constructor you can expose the class to the QML like so:

    qml->setContextProperty("HelloBB", this);

And then create a method in the C++ that you will be able to call from the QML. Remember, the method has to be marked as Q_INVOKABLE to be called from the QML.

Consider this:

        In HelloBB.hpp:

    public:
Q_INVOKABLE void test();

        In HelloBB.cpp:

    void HelloBB::test() {
qDebug() << "TEST";
}

        In main.qml:

   onClicked: {
HelloBB.test ()
}

Access an attribute c++ object from QML

You could do any of the following:

Add a public slot in API class:

API.cpp:
QString API::getUserName()
{
return user.getName();
}

main.qml:
Component.onCompleted: console.log( API.getUserName() )

Make User a Q_PROPERTY in API class:

API.h:
Q_PROPERTY( User* user READ user NOTIFY userChanged)

main.qml:
Component.onCompleted: console.log( API.user.getName() )

Register User with QML:

main.cpp:
qmlRegisterType<User>("MyUser", 1, 0, "MyUser");

main.qml:
Component.onCompleted: console.log( API.getUser().getName() )

To access QML component in C++ backend

You should use QObject::findChild() to locate the object, and simply invoke the signal as you would a nominal method.

But there is a catch, as QQuickRectangle itself is a private class, so it is not directly available for use in the C++ API. Also, it doesn't really have a clicked() signal, not unless you implemented one yourself. And if you did, it won't be part of the C++ interface.

Also, there is no onClicked() signal, the signal is clicked() and onClicked: is the handler hook.

However, you can still emit it using the Qt meta system, just use:

QObject * object = engine.rootObjects().at(0)->findChild<QObject *>("yourObjectName");
if (object) QMetaObject::invokeMethod(object, "clicked");

It will work even if the signal is implemented on the QML side, it will work even without casting to the concrete C++ type.

Now, if your object is not directly in the root object tree, you will not be able to find it and will have no choice but to pass a reference to it from the QML side to a C++ slot or invokable function.

QML instantiates C++ objects. How do I access their methods?

You want to obtain an object created in QML by C++, here it does not matter if the target has a prototype created in C ++ or not. If you want this you must obtain the object through findChild since all the objects created in QML have a kinship relationship with the window.

main.cpp

#include <QtQuick>
#include <QtGui>

class MyClass: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
Q_INVOKABLE void invokable(){
qDebug()<< "invokable";
}
Q_SLOT void slot(){
qDebug()<< "slot";
}
void function(){
qDebug()<< "function";
}
};

int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
qmlRegisterType<MyClass>("foo", 1, 0, "MyClass");
QGuiApplication app(argc, argv);

QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
view.show();
if(MyClass* myclass_instance = view.findChild<MyClass *>("myclass_instance")){
myclass_instance->invokable();
myclass_instance->slot();
myclass_instance->function();
}
return app.exec();
}
#include "main.moc"

main.qml

import QtQuick 2.9
import foo 1.0

Rectangle {
color: "salmon"
width: 640
height: 480
MyClass{
objectName: "myclass_instance"
}
}

But this method has several drawbacks such as who manages the life cycle of the object is QML, not C ++ so the pointer could at some point point to an unreserved address. Another disadvantage is that there is a dependency of C++ to QML since if the objectName is changed in QML the code in C ++ would have to be changed.


Another approach is to create a helper class that is exported to QML with setContextProperty() and that interacts with the MyClass object.

main.cpp

#include <QtQuick>
#include <QtGui>

class MyClass: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
Q_INVOKABLE void invokable(){
qDebug()<< "invokable";
}
Q_SLOT void slot(){
qDebug()<< "slot";
}
void function(){
qDebug()<< "function";
}
};

class Helper: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
void call_function(){
emit called();
}
Q_SIGNAL void called();
};

int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
qmlRegisterType<MyClass>("foo", 1, 0, "MyClass");
QGuiApplication app(argc, argv);

Helper helper;

QQuickView view;
view.rootContext()->setContextProperty("helper", &helper);
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
view.show();

helper.call_function();
return app.exec();
}
#include "main.moc"

main.qml

import QtQuick 2.9
import foo 1.0

Rectangle {
color: "salmon"
width: 640
height: 480
MyClass{
id: myclass
}
Connections{
target: helper
onCalled:{
myclass.invokable()
myclass.slot()
}
}
}

The advantage of this method is that there is no dependence between the logic of C++ and QML, besides the life cycle does not generate problems since the myclass objects are not handled directly in QML. The disadvantage is that you write a little more code and you can only call the Q_INVOKABLE or Q_SLOT.

Can't access C++ QObject subclass methods from QML

DerivedClass is missing Q_OBJECT macro (it is not inherited!).

Then simply run qmake again on your project & compile: it should work.



Related Topics



Leave a reply



Submit