我们知道, 在QML中我们可以很容易地调用C++代码. 同样, 我们可以在C++中调用放在QML中的Javascript代码. 由于存在函数/方法之间的调用, 数据类型之间的转换是比不可少的.在今天的文章中,我们来简单地介绍一下如何互相调用及一些类型的转换.
我们可以在文章"QML Basic Types"及"Data Type Conversion Between QML and C++"中得到更多的信息.
如何从C++中调用QML中的Javascript代码
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QDate>
#include <QMetaObject>
#include <QVariant>
#include <QArgument>
#include <QQuickItem>
#include <QQmlContext>
#include "cmyclass.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:///Main.qml")));
view.setResizeMode(QQuickView::SizeRootObjectToView);
QVariantList list;
list << 10 << QColor(Qt::green) << "bottles";
QVariantMap map;
map.insert("language", "QML");
map.insert("released", QDate(2010, 9, 21));
QMetaObject::invokeMethod(view.rootObject(), "readValues",
Q_ARG(QVariant, QVariant::fromValue(list)),
Q_ARG(QVariant, QVariant::fromValue(map)));
MyClass myclass;
view.rootContext()->setContextProperty("myclass", &myclass);
view.show();
return app.exec();
}
QMetaObject::invokeMethod(view.rootObject(), "readValues",
Q_ARG(QVariant, QVariant::fromValue(list)),
Q_ARG(QVariant, QVariant::fromValue(map)));
调用一个在Main.qml中定义的一个叫做readValues()的Javascript方法:
import QtQuick 2.0
import Ubuntu.Components 1.1
/*!
\brief MainView with a Label and Button elements.
*/
MainView {
// objectName for functional testing purposes (autopilot-qt5)
objectName: "mainView"
// Note! applicationName needs to match the "name" field of the click manifest
applicationName: "dataconversion.liu-xiao-guo"
/*
This property enables the application to change orientation
when the device is rotated. The default is false.
*/
//automaticOrientation: true
// Removes the old toolbar and enables new features of the new header.
useDeprecatedToolbar: false
width: units.gu(60)
height: units.gu(85)
function readValues(anArray, anObject) {
for (var i = 0; i < anArray.length; i++ )
console.log("Array item:", anArray[ i ])
for (var prop in anObject) {
console.log("Object item:", prop, "=", anObject[prop])
}
}
Page {
title: i18n.tr("dataconversion")
Button {
anchors.centerIn: parent
text: "Call C++ to pass array and object"
onClicked: {
var i = {
"from" : "xiaoguo.liu@company.com",
"to" : "y@mail.com",
"message" : "This is teriffic!"
};
var j = ["Saab", "Volvo", "BMW"];
myclass.callingFromQml(j, i);
}
}
}
}
qml: Array item: 10
qml: Array item: #00ff00
qml: Array item: bottles
qml: Object item: language = QML
qml: Object item: released = 周二 9月 21 00:00:00 2010 GMT+0800
我们可以看出来QVariantList被映射到Javascript的Array,而QVariantMap被映射到我们Javacript中的Object.这个概念是非常重要的.我们可以在" QML Basic Types"中找到更多的关于类型之间的映射.
同样,我们可以在Javascript中调用一个定义在C++代码中的方法,并把我们所需要的参数传人,进而得到解析.
Button {
anchors.centerIn: parent
text: "Call C++ to pass array and object"
onClicked: {
var i = {
"from" : "xiaoguo.liu@company.com",
"to" : "y@mail.com",
"message" : "This is teriffic!"
};
var j = ["Saab", "Volvo", "BMW"];
myclass.callingFromQml(j, i);
}
}
这里myclass是定义在C++中的一个类的实例.我们调用callingFromQml()方法:
void MyClass::callingFromQml(QVariantList list, QVariantMap map) {
qDebug() << "It is called from QML!";
int count = list.count();
qDebug() << "count: " << list.count();
qDebug() << "The array values are: ";
for ( int i = 0; i < count; i++ ) {
QString value = list[i].toString();
qDebug() << "value: " << value;
}
qDebug() << "The object values are: ";
qDebug() << "map.from" << map["from"].toString();
qDebug() << "map.to" << map["to"].toString();
qDebug() << "map.message" << map["message"].toString();
}
这里cmyclass.h定义如下:
cmyclass.h
#ifndef CMYCLASS_H
#define CMYCLASS_H
#include <QObject>
#include <QVariantList>
#include <QVariantMap>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = 0);
Q_INVOKABLE void callingFromQml(QVariantList list, QVariantMap map);
signals:
public slots:
};
#endif // CMYCLASS_H
注意这里的Q_INVOKABLE,表明它是可以在QML中可以调用的.更多关于QML调用调用C++的介绍,请参阅文章" Exposing Attributes of C++ Types to QML".一般来说,QML可以调用C++ QObject类的如下成员:
- Properties
- Methods (providing they are public slots or flagged with Q_INVOKABLE)
- Signals
它的输出为:
It is called from QML!
count: 3
The array values are:
value: "Saab"
value: "Volvo"
value: "BMW"
The object values are:
map.from "xiaoguo.liu@company.com"
map.to "y@mail.com"
map.message "This is teriffic!"
整个应用的界面为: