您的位置:首页 > 编程语言 > C语言/C++

QML和C++代码之间互相调用及参数之间的转换

2015-09-09 10:42 507 查看
我们知道, 在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!"


整个应用的界面为:



整个项目的源码在:https://github.com/liu-xiao-guo/dataconversion
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: