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

我们知道, 在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!"

整个应用的界面为:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值