QML与C++相互调用函数并获得返回值

这篇博客主要讲解在qml端如何直接调用c++的函数并获得返回值,在c++端如何直接调用qml的函数并获得返回值;

主要以 map 或者 jsonobject、list 或者 jsonarray为主!

其他单个类型,常见的类型,例如QString、int等,就不演示了;一通百通。

目录

1 准备工作

1.1 C++端 

1.2 QML端

2 qml端直接调用c++端函数

3 c++端直接调用qml端函数

3.1 调用qml的qmlFuncObj函数

3.2 调用qml的qmlFuncList函数

4 代码汇总


1 准备工作

1.1 C++端 

定义自定义类型MyObject,并提供QJsonObject funcObj(QString name, int age); 和 QList<QString> funcList(QString name1, QString name2); 两个函数供qml调用;

注意在头文件定义时需要使用 Q_INVOKABLE 去修饰,否则qml端无法调用。

myobject.h

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QObject>
#include <QDebug>
#include <QJsonObject>
#include <QList>

class MyObject : public QObject
{
    Q_OBJECT

public:
    MyObject(QObject *parent = nullptr);  // 构造函数
    ~MyObject();

    static MyObject *getInstance();

    /// 返回obj
    Q_INVOKABLE QJsonObject funcObj(QString name, int age);
    /// 返回list
    Q_INVOKABLE QList<QString> funcList(QString name1, QString name2);
};

#endif // MYOBJECT_H

myobject.cpp

#include "myobject.h"

MyObject::MyObject(QObject *parent) : QObject(parent)
{

}

MyObject::~MyObject()
{
}

MyObject *MyObject::getInstance()
{
    static MyObject *obj = nullptr;
    if (!obj) {
        obj = new MyObject;
    }

    return obj;
}

QJsonObject MyObject::funcObj(QString name, int age)
{
    QJsonObject obj;
    obj.insert("name", name);
    obj.insert("age", age);

    return obj;
}

QList<QString> MyObject::funcList(QString name1, QString name2)
{
    QList<QString> list;
    list << name1 << name2 << "第三";

    return list;
}

这里的QJsonObject也可以是QVariantMap,注意不能是QMap类型,qml无法识别;

这里的QList<QString>也可以是QVector,QQJsonArray等类型;

main.cpp

然后再main函数中将MyObject注册为全局单例对象;

注意代码中已经提前获得了windowObj,即是qml的对象,用于下面调用qml函数使用。

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include <QQmlContext>
#include "myobject.h"


#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    // 获得全局对象,上下文对象
    QQmlContext *context = engine.rootContext();
    // 给qml设置一个全局变量;如果qml内部有定义重名变量,那么会优先使用qml内部定义的变量;另外,定义全局变量会有性能问题
    context->setContextProperty("SCREEN_WIDTH", 800);

    // 注册,在需要使用的地方 import MyObj 1.0
//    qmlRegisterType<MyObject>("MyObj", 1, 0, "MyObject");

    // 注册全局单例对象
    qmlRegisterSingletonInstance("MyObj", 1, 0, "MyObject", MyObject::getInstance());

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;


    // 在engine加载完成后,就可以获取qml的所有对象了
    QList<QObject*> list = engine.rootObjects();

    // list的首个元素就是window
    QObject *windowObj = list.first();

    return app.exec();
}

1.2 QML端

定义两个函数,function qmlSlot(name, age) 和 function qmlFuncObj(name, age) 供C++调用;

// 定义qml函数
function qmlFuncObj(name, age) {
    let obj = { };
    obj["name"] = name
    obj["age"] = age
    obj["sex"] = "man"

    return obj
    //return JSON.stringify(obj)  // 返回JSON字符串
}

// 定义qml函数
function qmlFuncList(name, age) {
    let list = [];
    list.push(name)
    list.push(age)
    list.push("666")

    return list
    //return JSON.stringify(list)  // 返回JSON字符串
}

2 qml端直接调用c++端函数

注意,调用的c++函数,在定义时,必须使用 Q_INVOKABLE 去修饰,否则在qml这里是无法调用的。

如下:

/// 返回obj
Q_INVOKABLE QJsonObject funcObj(QString name, int age);
/// 返回list
Q_INVOKABLE QList<QString> funcList(QString name1, QString name2);

 然后,就可以在qml端直接调用c++的函数了,使用 let 定义变量接收返回值即可!

Button {
    width: 100; height: 50
    objectName: "myButton"
    onClicked: {
        // 直接调用c++函数
        let obj = MyObject.funcObj("小明", 99)
        console.log("name:", obj["name"], "   age:", obj["age"])

        let list = MyObject.funcList("第一", "第二");
        console.log("count:", list.length)

        // 遍历方式一
        for (let i = 0; i < list.length; ++i) {
            console.log("list:", list[i])
        }
        // 遍历方式二
        for (const item of list) {
            console.log(item);
        }
    }
}

通过点击按钮后,即可调用c++函数,并且得到返回值做打印:

3 c++端直接调用qml端函数

在c++中调用qml的函数,需要使用到QMetaObject::invokeMethod函数,其是重载函数;

函数原型:

static inline bool invokeMethod(QObject *obj, const char *member,
                         QGenericReturnArgument ret,
                         QGenericArgument val0 = QGenericArgument(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())
{
    return invokeMethod(obj, member, Qt::AutoConnection, ret, val0, val1, val2, val3,
            val4, val5, val6, val7, val8, val9);
}

参数一:qml对象指针;

参数二:调用qml的函数名;

参数三:调用函数的返回值;

剩余参数:调用qml函数的传参参数;

返回值:调用成功返回true,其他返回false。

当然,还有很多函数重载,这里主要介绍有返回值的,其他那些都类似。

注意,定义接收函数返回的类型变量和传参的函数变量使用的类型均是QVaraint类型。有兴趣的可以尝试一下目标类型,看下行不行。

3.1 调用qml的qmlFuncObj函数

// 定义接受的返回值
QVariant res;
// 定义参数
QVariant arg_name = "jtom";
QVariant arg_age = 26;
// 调用qml函数
bool flag = QMetaObject::invokeMethod(windowObj, "qmlFuncObj",
                          Q_RETURN_ARG(QVariant, res),
                          Q_ARG(QVariant, arg_name),
                          Q_ARG(QVariant, arg_age));
qDebug() << "res = " << res;

windowObj 是 qml的对象指针,在准备工作中已经获得!

通过打印res返回查看,得到返回结果是一个QJSValue类型,是一个JavaScript类型。

如果需要获得QJsonObject类型,则需要将res转成QJSValue类型后,再转成QVaraint类型,再转成QJsonObject类型;

如果需要获得QMap类型,则需要将res转成QJSValue类型后,再转成QVaraint类型,再转成QMap类型;

if (flag) {
    QJSValue jsValue = res.value<QJSValue>();

    // 方式一,转换为 QJsonObject
    QJsonObject jsonObj = jsValue.toVariant().toJsonObject();
    qDebug() << jsonObj << "  " << jsonObj["name"] << "  " << jsonObj["age"] << "  " << jsonObj["sex"];


    // 方式二,转换为QMap
    QMap<QString, QVariant> map = jsValue.toVariant().toMap();
    qDebug() << map;
}

注意,以上前提是调用qml函数返回的是QJSValue类型;

当然,返回时,也可以直接返回json字符串,那么接收到后就可以直接转成QJsonDocument去处理了。

在qml函数中,将obj转成json字符串后再返回,如下:

function qmlFuncObj(name, age) {
    let obj = { };
    obj["name"] = name
    obj["age"] = age
    obj["sex"] = "man"

    //return obj
    return JSON.stringify(obj)  // 返回JSON字符串
}

然后就可以当作json字符串的方式去处理解析了,如下:

if (flag) {
    QJsonDocument doc = QJsonDocument::fromJson(res.toString().toUtf8());
    QJsonObject jsonObj = doc.object();
    qDebug() << jsonObj << "  " << jsonObj["name"] << "  " << jsonObj["age"] << "  " << jsonObj["sex"];
}

可以看出,转为json字符串返回后,c++接收到的类型不再是QJSValue类型,而是QString类型。

3.2 调用qml的qmlFuncList函数

// 定义接收返回值变量
QVariant res;
// 定义参数
QVariant arg_name = "jtom";
QVariant arg_age = "266";
// 调用qml函数
bool flag = QMetaObject::invokeMethod(windowObj, "qmlFuncList",
                          Q_RETURN_ARG(QVariant, res),
                          Q_ARG(QVariant, arg_name),
                          Q_ARG(QVariant, arg_age));

qDebug() << "res = " << res;

可以看出,返回值也是一个QJSValue类型,处理方式与上面类似了。

if (flag) {
    // 方法1:转换为 QVariantList(推荐)
    QVariantList list = res.toList();
    qDebug() << "List:" << list;
    qDebug() << "Elements:" << list[0] << list[1] << list[2];

    // 方法2:转换为 QJsonArray
    QJsonArray jsonArray = QJsonArray::fromVariantList(res.toList());
    qDebug() << "JSON Array:" << jsonArray;
}

注意,以上前提是调用qml函数返回的是QJSValue类型;

当然,返回时,也可以直接返回json字符串,那么接收到后就可以直接转成QJsonDocument去处理了。

在qml函数中,将list转成json字符串后再返回,如下:

function qmlFuncList(name, age) {
    let list = [];
    list.push(name)
    list.push(age)
    list.push("666")

//        return list;
    return JSON.stringify(list)
}

然后就可以当作json字符串的方式去处理解析了,如下:

if (flag) {
    QJsonDocument doc = QJsonDocument::fromJson(res.toString().toUtf8());
    QJsonArray jsonArr = doc.array();
    qDebug() << jsonArr;
}

可以看出,转为json字符串返回后,c++接收到的类型不再是QJSValue类型,而是QString类型。

4 代码汇总

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include <QQmlContext>
#include "myobject.h"


#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    // 获得全局对象,上下文对象
    QQmlContext *context = engine.rootContext();
    // 给qml设置一个全局变量;如果qml内部有定义重名变量,那么会优先使用qml内部定义的变量;另外,定义全局变量会有性能问题
    context->setContextProperty("SCREEN_WIDTH", 800);

    // 注册,在需要使用的地方 import MyObj 1.0
//    qmlRegisterType<MyObject>("MyObj", 1, 0, "MyObject");

    qmlRegisterSingletonInstance("MyObj", 1, 0, "MyObject", MyObject::getInstance());

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;


    // 在engine加载完成后,就可以获取qml的所有对象了
    QList<QObject*> list = engine.rootObjects();

    // list的首个元素就是window
    QObject *windowObj = list.first();


   {
        // 定义接受的返回值
        QVariant res;
        // 定义参数
        QVariant arg_name = "jtom";
        QVariant arg_age = 26;
        // 调用qml函数
        bool flag = QMetaObject::invokeMethod(windowObj, "qmlFuncObj",
                                  Q_RETURN_ARG(QVariant, res),
                                  Q_ARG(QVariant, arg_name),
                                  Q_ARG(QVariant, arg_age));

        qDebug() << "res = " << res;
//        if (flag) {
//            QJSValue jsValue = res.value<QJSValue>();

//            // 方式一,转换为 QJsonObject
//            QJsonObject jsonObj = jsValue.toVariant().toJsonObject();
//            qDebug() << jsonObj << "  " << jsonObj["name"] << "  " << jsonObj["age"] << "  " << jsonObj["sex"];


//            // 方式二,转换为QMap
//            QMap<QString, QVariant> map = jsValue.toVariant().toMap();
//            qDebug() << map;
//        }

        if (flag) {
            QJsonDocument doc = QJsonDocument::fromJson(res.toString().toUtf8());
            QJsonObject jsonObj = doc.object();
            qDebug() << jsonObj << "  " << jsonObj["name"] << "  " << jsonObj["age"] << "  " << jsonObj["sex"];
        }
    }


    {
        // 定义接受的返回值
        QVariant res;
        // 定义参数
        QVariant arg_name = "jtom";
        QVariant arg_age = "266";
        // 调用qml函数
        bool flag = QMetaObject::invokeMethod(windowObj, "qmlFuncList",
                                  Q_RETURN_ARG(QVariant, res),
                                  Q_ARG(QVariant, arg_name),
                                  Q_ARG(QVariant, arg_age));

        qDebug() << "res = " << res;
//        if (flag) {
//            // 方法1:转换为 QVariantList(推荐)
//            QVariantList list = res.toList();
//            qDebug() << "List:" << list;
//            qDebug() << "Elements:" << list[0] << list[1] << list[2];

//            // 方法2:转换为 QJsonArray
//            QJsonArray jsonArray = QJsonArray::fromVariantList(res.toList());
//            qDebug() << "JSON Array:" << jsonArray;
//        }

        if (flag) {
            QJsonDocument doc = QJsonDocument::fromJson(res.toString().toUtf8());
            QJsonArray jsonArr = doc.array();
            qDebug() << jsonArr;
        }
    }

    return app.exec();
}

main.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.14

import MyObj 1.0    // 导入自定义模块

Window {
    id: root
    visible: true
    width: SCREEN_WIDTH
    height: 500
    title: qsTr("Hello World")
    color: "white"
    objectName: "window"


    // 定义qml端槽函数
    function qmlSlot(name, age) {
        console.log("qml:name = ", name, "   age = ", age);
    }


    // 定义qml函数
    function qmlFuncObj(name, age) {
        let obj = { };
        obj["name"] = name
        obj["age"] = age
        obj["sex"] = "man"

        //return obj
        return JSON.stringify(obj)  // 返回JSON字符串
    }

    // 定义qml函数
    function qmlFuncList(name, age) {
        let list = [];
        list.push(name)
        list.push(age)
        list.push("666")

//        return list;
        return JSON.stringify(list)
    }


    Button {
        width: 100; height: 50
        objectName: "myButton"
        onClicked: {

            let obj = MyObject.funcObj("小明", 99)
            console.log("obj:", obj, "   name:", obj["name"], "   age:", obj["age"])

            let list = MyObject.funcList("第一", "第二");
            console.log("list:", list, "   count:", list.length)

//            // 遍历方式一
            for (let i = 0; i < list.length; ++i) {
                console.log("list:", list[i])
            }
//            // 遍历方式二
            for (const item of list) {
                console.log(item);
            }
        }
    }
}

qml与c++相互调用函数已经介绍完毕,具体用法看具体项目吧!

C++程序中使用QML QML API是分为三个主类——QDeclarativeEngine, QdeclarativeComponent QDeclarativeContext。QDeclarativeEngine 提供QML运行的环境,QdeclarativeComponent 封装了QML Documents QDeclarativeContext允许程序导出数据到QML组件实例。 QML还包含了API的一个方便,通过QDeclarativeView 应用程序只需要简单嵌入QML组件到一个新的QGraphicsView就可以了。这有许多细节将在下面讨论。QDeclarativeView 主要是用于快速成型的应用程序里。 如果你是重新改进使用QMLQt应用程序,请参阅 整合QML到现有的Qt UI代码。 基本用法 每个应用程序至少需求一个QDeclarativeEngine。QDeclarativeEngine允许配置全局设置应用到所有的QML组件实例中,例如QNetworkAccessManager是用于网络通信以及永久储存的路径。如果应用程序需求在QML组件实例间需求不同的设置只需要多个QDeclarativeEngine。 使用QDeclarativeComponent类载入QML Documents。每个QDeclarativeComponent实例呈现单一QML文档。QDeclarativeComponent可以传递一个文档的地址或文档的原始文本内容。该文档的URL可以是本地文件系统的地址或通过QNetworkAccessManager支持的网络地址。 QML组件实例通过调用QDeclarativeComponent::create()模式来创建。在这里载入一个QML文档的示例且从它这里创建一个对象。 QDeclarativeEngine *engine = new QDeclarativeEngine(parent); QDeclarativeComponent component(engine, QUrl::fromLocalFile(“main.qml”)); QObject *myObject = component.create(); 导出数据 QML组件是以QDeclarativeContext实例化的。context允许应用程序导出数据到该QML组件实例中。单个QDeclarativeContext 可用于一应用程序的所有实例对象或针对每个实例使用QDeclarativeContext 可以创建更为精确的控制导出数据。如果不传递一个context给QDeclarativeComponent::create()模式;那么将使用QDeclarativeEngine的root context。数据导出通过该root context对所有对象实例是有效的。 简单数据 为了导出数据到一个QML组件实例,应用程序设置Context属性;然后由QML属性绑定的名称JavaScrip访问。下面的例子显示通过QGraphicsView如何导出一个背景颜色到QML文件中: //main.cpp #include <QApplication> #include <QDeclarativeView> #include <QDeclarativeContext> int main(int argc, char *argv[]) { QApplication app(argc, argv); QDeclarativeView view; QDeclarativeContext *context = view.rootContext(); context->setContextProperty(“backgroundColor”, QColor(Qt::yellow)); view.setSource(QUrl::fromLocalFile(“main.qml”)); view.show(); return app.exec(); } //main.qml import Qt 4.7 Rectangle { width: 300 height: 300 color: backgroundColor Text { anchors.centerIn: parent text: “Hello Yellow World!” } } 或者,如果你需要main.cpp不需要在QDeclarativeView显示创建的组件,你就需要使用QDeclarativeEngine::rootContext()替代创建QDeclarativeContext实例。 QDeclarativeEngine engine; QDeclarativeContext *windowContext = new QDeclarativeContext(engine.rootContext()); windowContext->setContextProperty(“backgroundColor”, QColor(Qt::yellow)); QDeclarativeComponent component(&engine, “main.qml”); QObject *window = component.create(windowContext); Context属性的操作像QML绑定的标准属性那样——在这个例子中的backgroundColor Context属性改变为红色;那么该组件对象实例将自动更新。注意:删除任意QDeclarativeContext的构造是创建者的事情。当window组件实例撤消时不再需要windowContext时,windowContext必须被消毁。最简单的方法是确保它设置window作为windowContext的父级。 QDeclarativeContexts 是树形结构——除了root context每个QDeclarativeContexts都有一个父级。子级QDeclarativeContexts有效的继承它们父级的context属性。这使应用程序分隔不同数据导出到不同的QML对象实例有更多自由性。如果QDeclarativeContext设置一context属性,同样它父级也被影响,新的context属性是父级的影子。如下例子中,background context属性是Context 1,也是root context里background context属性的影子。 结构化数据 context属性同样可用于输出结构化写数据到QML对象。除了QVariant支持所有已经存在的类型外,QObject 派生类型可以分配给context属性。 QObject context属性允许数据结构化输出允许QML来设置值。 下例创建CustomPalette对象设置它作为palette context属性。 class CustomPalette : public QObject { Q_OBJECT Q_PROPERTY(QColor background READ background WRITE setBackground NOTIFY backgroundChanged) Q_PROPERTY(QColor text READ text WRITE setText NOTIFY textChanged) public: CustomPalette() : m_background(Qt::white), m_text(Qt::black) {} QColor background() const { return m_background; } void setBackground(const QColor &c) { if (c != m_background) { m_background = c; emit backgroundChanged(); } } QColor text() const { return m_text; } void setText(const QColor &c) { if (c != m_text) { m_text = c; emit textChanged(); } } signals: void textChanged(); void backgroundChanged(); private: QColor m_background; QColor m_text; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); QDeclarativeView view; view.rootContext()->setContextProperty(“palette”, new CustomPalette); view.setSource(QUrl::fromLocalFile(“main.qml”)); view.show(); return app.exec(); } QML引用palette对象以及它的属性,为了设置背景文本的颜色,这里是当单击窗口时,面板的文本颜色将改变成蓝色。 import Qt 4.7 Rectangle { width: 240 height: 320 color: palette.background Text { anchors.centerIn: parent color: palette.text text: “Click me to change color!” } MouseArea { anchors.fill: parent onClicked: { palette.text = “blue”; } } } 可以检测一个C++属性值——这种情况下的CustomPalette的文本属性改变,该属性必须有相应的NOTIFY信息。NOTIFY信号是属性值改变时将指定一个信号发射。 实现者应该注意的是,只有值改变时才发射信号,以防止发生死循环。访问一个绑定的属性,没有NOTIFY信号的话,将导致QML在运行时发出警告信息。 动态结构化数据 如果应用程序对结构化过于动态编译QObject类型;那么对动态结构化数据可在运行时使用QDeclarativePropertyMap 类构造。 从QML调用 C++ 通过public slots输出模式或Q_INVOKABLE标记模式使它可以调用QObject派生出的类型。 C++模式同样可以有参数且可以返回值QML支持如下类型: •bool •unsigned int, int •float, double, qreal •QString •QUrl •QColor •QDate,QTime,QDateTime •QPoint,QPointF •QSize,QSizeF •QRect,QRectF •QVariant 下面例子演示了,当MouseArea单击时控制“Stopwatch”对象的开关。 //main.cpp class Stopwatch : public QObject { Q_OBJECT public: Stopwatch(); Q_INVOKABLE bool isRunning() const; public slots: void start(); void stop(); private: bool m_running; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); QDeclarativeView view; view.rootContext()->setContextProperty(“stopwatch”, new Stopwatch); view.setSource(QUrl::fromLocalFile(“main.qml”)); view.show(); return app.exec(); } //main.qml import Qt 4.7 Rectangle { width: 300 height: 300 MouseArea { anchors.fill: parent onClicked: { if (stopwatch.isRunning()) stopwatch.stop() else stopwatch.start(); } } } 值得注意的是,在这个特殊的例子里有更好的方法来达到同样的效果,在main.qml有”running”属性,这将会是一个非常优秀的QML代码: // main.qml import Qt 4.7 Rectangle { MouseArea { anchors.fill: parent onClicked: stopwatch.running = !stopwatch.running } } 当然,它同样可以调用 functions declared in QML from C++。 网络组件 如果URL传递给QDeclarativeComponent是一网络资源或者QML文档引用一网络资源,QDeclarativeComponent要先获取网络数据;然后才可以创建对象。在这种情况下QDeclarativeComponent将有Loading status。直到组件调用QDeclarativeComponent::create()之前,应用程序将一直等待。 下面的例子显示如何从一个网络资源载入QML文件。在创建QDeclarativeComponent之后,它测试组件是否加载。如果是,它连接QDeclarativeComponent::statusChanged()信号,否则直接调用continueLoading()。这个测试是必要的,甚至URL都可以是远程的,只是在这种情况下要防组件是被缓存的。 MyApplication::MyApplication() { // … component = new QDeclarativeComponent(engine, QUrl(“http://www.example.com/main.qml”)); if (component->isLoading()) QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), this, SLOT(continueLoading())); else continueLoading(); } void MyApplication::continueLoading() { if (component->isError()) { qWarning() << component->errors(); } else { QObject *myObject = component->create(); } } Qt资源 QML的内容可以使用qrc:URL方案从Qt 资源系统载入。例如: [project/example.qrc] <!DOCTYPE RCC> <RCC version=”1.0″> <qresource prefix=”/”> <file>main.qml</file> <file>images/background.png</file> </qresource> </RCC> [project/project.pro] QT += declarative SOURCES += main.cpp RESOURCES += example.qrc [project/main.cpp] int main(int argc, char *argv[]) { QApplication app(argc, argv); QDeclarativeView view; view.setSource(QUrl(“qrc:/main.qml”)); view.show(); return app.exec(); } [project/main.qml] import Qt 4.7 Image { source: “images/background.png” } 请注意,资源系统是不能从QML直接访问的。如果主QML文件被加载作为资源,所有的文件指定在QML中做为相对路径从资源系统载入。在QML层使用资源系统是完全透明的。这也意味着,如果主QML文件没有被加载作为资源,那么从QML不能访问资源系统。 1.这里主要是介绍,如何在c++调用QML中的函数和设置QML中的属性的问题 2.具体代码 // UICtest.qml import Qt 4.7 Rectangle { id: mainWidget; width: 640 height: 480 function callbyc(v) { mainWidget.color = v; return "finish"; } Rectangle{ id: secondRect; x: 100; y: 20; width: 400; height: 300; Rectangle{ x: 10; y: 20; width: 30; height: 40; color: "#FF035721" Text { objectName: "NeedFindObj"; anchors.fill: parent; text: ""; } } } } // main.cpp #include <QtGui/QApplication> #include <QtDeclarative/QDeclarativeView> #include <QtDeclarative/QDeclarativeEngine> #include <QtDeclarative/QDeclarativeComponent> #include <QtDeclarative/QDeclarativeContext> #include <QtDeclarative/QDeclarativeItem> #include <QMetaObject> int main(int argc, char *argv[]) { QApplication a(argc, argv); QDeclarativeView qmlView; qmlView.setSource(QUrl::fromLocalFile("../UICtest/UICtest.qml")); qmlView.show(); // 获取根节点,就是 QML中 id是mainWidget的节点 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(qmlView.rootObject()); item->setProperty("color", QVariant("blue")); // 查找到我们需要的节点根均objectname NeedFindObj 来获得设置他的文本属性 QDeclarativeItem *item1 = item->findChild<QDeclarativeItem *>("NeedFindObj"); if (item1) { item1->setProperty("text", QVariant("OK")); } // 调用QML中的函数, 分别是 函数所在的对象, 函数名,返回值, 参数 QVariant returnVar; QVariant arg1 = "blue"; QMetaObject::invokeMethod(item, "callbyc", Q_RETURN_ARG(QVariant, returnVar),Q_ARG(QVariant, arg1)); qDebug(" %s",returnVar.toString().toLocal8Bit().data()); return a.exec(); } 说明: 这里的根节点是id为mainWidget的矩形元素,那么在C++中获取根节点后就可以,直接的设置他的属性了。其他属性也可以同样,调用指定节点内的函数是通过QMetaObject中的invokeMethod 来进行调用的。 最后所有关于QMLc++交互部分就基本写完,如果想要更多的东西,或者一些其他方法,强烈看看 http://doc.qt.nokia.com/4.7-snapshot/qtbinding.html,或者帮助文档,(究竟是不是我的文档里面没有还是怎么的)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpp_learners

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值