2014年8月27日 星期三

C++傳遞結構物件給QML ( Interacting with QML Objects from C++ )

當要傳送結構性物件給QML時,可以利用QVariantList及QVariantMap,因為QML Engine提供型態自動轉換的功能,QVariantList對應Javascript的Array,QVariantMap對應Javascript的objects。

<C++>
QVariantList list;
list << 10 << "Marc";

<QML>
for( var i = 0; i < anArray.length; i++){
 console.log("Array item:", anArray[i])
}

<C++>
QVariantMap map;
map.insert("itemKey1", "value");
map.insert("itemKey2", 20);

<QML>

for( var prop in anObject ){
 console.log("Object item:", prop, "=", anObject[prop])
}


以下的範例執行後,按下Set按鍵會從QML傳送"Alice"的字串給C++,然後C++會組出一個物件傳回去給QML。

<pro>
TEMPLATE = app

QT += qml quick widgets

SOURCES += main.cpp \
    controller.cpp

RESOURCES += qml.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Default rules for deployment.
include(deployment.pri)

HEADERS += \
    controller.h

<controller.h>
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <QObject>
#include <QVariantList>
#include <QVariantMap>
#include <QVariant>
#include <QPoint>
#include <QRect>

class Controller : public QObject
{
    Q_OBJECT
public:
    explicit Controller(QObject *parent = 0);
    void initialize( QObject* qObj );

signals:
    void updateData( QVariant object );

public slots:
    void setData( QString name );

private:
    QObject* viewItem;
private:
    QVariant addData( QString name );
};

#endif // CONTROLLER_H

<controller.cpp>
#include "controller.h"
#include <QDebug>

Controller::Controller(QObject *parent) :
    QObject(parent)
{
}

void Controller::initialize(QObject *qObj)
{
    this->viewItem = qObj;
    QObject::connect( viewItem, SIGNAL( qmlSetName(QString)),
                      this, SLOT( setData(QString)) );
    QObject::connect( this, SIGNAL( updateData(QVariant)),
                      viewItem, SLOT( qmlUpdateObject(QVariant)) );
}

void Controller::setData(QString name)
{
    QVariantList list;
    list<<addData("Marc")<<addData("David")
       <<addData("Sam")<<addData(name);
    
    emit updateData(list);
}

QVariant Controller::addData( QString name )
{
    QVariantMap qVarPoints;
    qVarPoints.insert("Point1", QPoint(20,25));
    qVarPoints.insert("Point2", QPoint(35,25));

    QVariantMap map;
    map.insert("Name", name);
    map.insert("Id", 2);
    map.insert("Rect", QRect( 5, 9, 21, 25 ));
    map.insert("Points", qVarPoints);

    return QVariant(map);
}

<main.cpp>

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include "controller.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
    QObject* topLevel     = engine.rootObjects().first();
    QQuickWindow* rootWin = qobject_cast<QQuickWindow *>( topLevel );

    Controller *controller = new Controller();
    controller->initialize( rootWin );

    return app.exec();
}

<main.qml>

import QtQuick 2.2
import QtQuick.Controls 1.1

ApplicationWindow {
    id      : mainWin
    visible : true
    width   : 320
    height  : 240
    title   : qsTr("C++ and QML Integration")

    signal qmlSetName( string name )

    function showInformation( Object ){
        for (var prop in Object) {
            switch( prop )
            {
            case "Points":
                for (var subProp in Object[prop]) {
                    console.log(subProp, "=", Object[prop][subProp])
                }
                break;
            case "Name":
                console.log(prop, "=", Object[prop])
                break;
            case "Id":
                console.log(prop, "=", Object[prop])
                break;
            case "Rect":
                console.log(prop, "=", Object[prop])
                break;
            default:
                break;
            }
        }
    }

    function qmlUpdateObject( Object ){
        for ( var i = 0; i < Object.length; i++){
            console.log("-------------------")
            showInformation(Object[i])
        }
    }

    menuBar: MenuBar {
        Menu {
            title: qsTr("Control")
            MenuItem {
                text: qsTr("Set Name")
                onTriggered: {
                    mainWin.qmlSetName("Alice")
                }
            }
        }
    }

    Text {
        id  : txtName
        text: qsTr("C++ and QML Integration")
        anchors.centerIn: parent
    }
}


0 意見:

張貼留言