C++ calls the qml function through the following functions:
bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret,
QGenericArgument val0 = QGenericArgument( Q_NULLPTR ), QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(),
QGenericArgument val3 = QGenericArgument(), QGenericArgument val4 = QGenericArgument(), QGenericArgument val5 = QGenericArgument(), QGenericArgument val6 = QGenericArgument(),
QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument(), QGenericArgument val9 = QGenericArgument());
There are two commonly used macros here: Q_RETURN_ARG, Q_ARG, which can be seen from the literal meaning, one is used to get the return value, and the other is used to pass parameters. Below is an example:
QVariant returnedValue; QVariant msg = "message sended from C++"; QMetaObject::invokeMethod(pctrlobj, "setTextString", Q_RETURN_ARG(QVariant, returnedValue),Q_ARG(QVariant, msg));
Before applying this function to call the members of the qml object, the key is to obtain the qml object to be called. There are two ways to easily obtain the qml object:
1) Directly pass QOBject * from the qml side to the C++ side;
2) By setting objectName, use findChild() to find the corresponding object;
The first solution will not be discussed, it is very simple to implement, here is a brief explanation of the second solution, see the following example:
main.qml
import QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Controls 1.3 Window { id: windows; visible: true width: 640 height: 480 title: qsTr("Hello World") Button{ id: test; width: 70; height: 30; onClicked: test1.open(); } Test1{ id: test1; visible: false; onShowTest:{ } } function test() { console.log("test ok!"); } }
Test1.qml
import QtQuick 2.0 import QtQuick.Window 2.2 import QtQuick.Controls 1.3 Window { id: test; width: 300; height: 200; visible:false; signal showTest(); Button{ id: testButton; objectName:"testButton" //The object name is set here for findChild() to get the object; text:"click me"; onClicked:{ showTest(); } } function open() { test.visible = true; } function close() { test.visible = false; } }
main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QObject> int main(int argc, char *argv[]) { #if defined(Q_OS_WIN) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); QObject *pRoot = engine.rootObjects().first(); QObject *pButton = pRoot->findChild<QObject *>("testButton"); if( pButton ) { QObject::connect(pButton,SIGNAL(clicked()),pRoot,SLOT(test())); } if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }