您现在的位置是:网站首页> C/C++

C++与QML交互

  • C/C++
  • 2021-04-14
  • 1058人已阅读
摘要

C++与QML交互,可能是由于内容开始是网络地址(http://...)完整的英文词截取后不能换行造成 为避免代码造成手机端排版的混乱,可适当增加文字描述,将代码往后推移

将类注册上去

int main(int argc,char *argv[])

{

QGuiApplication app(argc,argv);

qmlRegisterType<ColorMaker>("an,qt.ColorMaker",1,0,"ColorMaker");


QQuickView viewer;

viewer.setResizeMod(QQuickView::SizeRootObjectToView);

viewer.setSource(qUrl("Qrc://main.qml"));

viewer.show();

return 

}

在QML中使用

import an.qt.ColorMaker 1.0

ColorMaker{

 id:colorMaker;

 color:Qt.green;

}

以属性方式

int main(int argc,char *argv[])

{

QGuiApplication app(argc,argv);

QQuickView  viewer;

viewer.setResizeMode(QQUickView::SizeRootObjectToView);

viewer.rootContext()->setContentProperty("colorMaker",new ColorMaker);

viewer.setSource(QUrl("qrc://main.qml");

viewer.show();

return app.exec();

}

一旦调用setContextProperty()导出了属性,就可以在QML中使用了,不需要import语句了

main.qml修改为

import QtQuick 2.2

import QtQuick.Controls 1.2

//import an.qt.ColorMaker 1.0


/*

ColorMaker{

 id:colorMaker;

 color:Qt.green;

}

*/

使用:

function(){

colorMaker.start();

}

C++中使用QML对象

QuickView获得,QQmlApplicationEngine

QuickView.engine()


QML文件

import QtQuick 2.9 

Item{

    id: root

    width: 100

    height: 100

    //自定义属性  --cpp可以访问

    property string msg: "gongjianbo1992"

    //自定义信号  --可以触发cpp槽函数

    signal qmlSendMsg(string msg) 

 

    Rectangle {

        anchors.fill: parent

        color: "green"

        objectName: "rect"

    }

 

    MouseArea {

        anchors.fill: parent

        onClicked: {

            console.log("qml clicked, send qmlSendMsg signal")

            root.qmlSendMsg(root.msg)

        }

    }

 

    onHeightChanged: console.log("qml height changed")

    onWidthChanged: console.log("qml width changed")

 

    //QML中的方法可以被cpp调用

    function qml_method(val_arg){

        console.log("qml method",val_arg)

        return "ok"

    }

}

在QML中我定义了一些属性和方法等,用于测试。 


//file CppObj.h

#ifndef CPPOBJ_H

#define CPPOBJ_H

 

#include <QObject>

#include <QDebug>

 

class CppObj : public QObject

{

    Q_OBJECT

public:

    explicit CppObj(QObject *parent = Q_NULLPTR)

        :QObject(parent){}

 

public slots:

    //槽函数 --用来接收qml的信号

    void cppRecvMsg(const QString &msg){

        qDebug()<<"cpp recv msg"<<msg;

    }

};

 

#endif // CPPOBJ_H

Cpp中定义了一个槽函数,用来接收QML对象的信号。 


//file main.cpp

#include <QGuiApplication>

#include <QQmlProperty>

#include <QQuickView>

#include <QQuickItem>

#include <QMetaObject>

#include <QDebug>

 

#include "CppObj.h"

 

int main(int argc, char *argv[])

{

    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

 

    QGuiApplication app(argc, argv);

 

    //可以使用QQmlComponent或QQuickView的C++代码加载QML文档

    //QQuickView不能用Window做根元素

    QQuickView view(QUrl("qrc:/main.qml"));

    view.show();

 

    QObject *qmlObj=view.rootObject();

    /* 应该始终使用QObject::setProperty()、QQmlProperty

     * 或QMetaProperty::write()来改变QML的属性值,

     * 以确保QML引擎感知属性的变化。

     */

    //通过QObject设置属性值

    //qmlObj->setProperty("height",200);

    QQmlProperty(qmlObj,"height").write(200);

    //通过QObject获取属性值

    qDebug()<<"qml root height"<<qmlObj->property("height");

    //任何属性都可以通过C++访问

    qDebug()<<"qml property msg"<<qmlObj->property("msg");

 

    QQuickItem *item=qobject_cast<QQuickItem*>(qmlObj);

    //通过QQuickItem设置属性值

    item->setWidth(200);

    //通过QQuickItem获取属性值

    qDebug()<<"qml root width"<<item->width();

 

    //通过objectName访问加载的QML对象

    //QObject::findChildren()可用于查找具有匹配objectName属性的子项

    QObject *qmlRect=qmlObj->findChild<QObject*>("rect");

    if(qmlRect){

        qDebug()<<"qml rect color"<<qmlRect->property("color");

    }

 

    //调用QML方法

    QVariant val_return;       //返回值

    QVariant val_arg="=.=!";   //参数值

    //Q_RETURN_ARG()和Q_Arg()参数必须制定为QVariant类型

    QMetaObject::invokeMethod(qmlObj,

                              "qml_method",

                              Q_RETURN_ARG(QVariant,val_return),

                              Q_ARG(QVariant,val_arg));

    qDebug()<<"qml method return value"<<val_return; //函数中返回“ok”

 

    //关联qml信号与cpp槽

    //如果信号参数为QML对象类型,信号用var参数类型,槽用QVariant类型接收

    CppObj cppObj;

    QObject::connect(qmlObj,SIGNAL(qmlSendMsg(QString)),

                     &cppObj,SLOT(cppRecvMsg(QString)));

 

    return app.exec();

}

然后就把文档中的东西测试了下,操作起来很简单。不想相对于QML中使用C++对象来说,感觉作用没那么大,毕竟QML访问C++也可以改变C++对象的状态,可能时我还没想到合适的应用场景。下面是我的测试输出结果:


QML debugging is enabled. Only use this in a safe environment.

qml: qml height changed

qml root height QVariant(double, 200)

qml property msg QVariant(QString, "gongjianbo1992")

qml: qml width changed

qml root width 200

qml rect color QVariant(QColor, QColor(ARGB 1, 0, 0.501961, 0))

qml: qml method =.=!

qml method return value QVariant(QString, "ok")

qml: qml clicked, send qmlSendMsg signal

cpp recv msg "gongjianbo1992"

 以上两种方式应该就是最简单的QML与C++交互应用了,对照文档或是博客敲一遍代码可以很容易地理解

int main(int argc,char *argv[])

{

QGuiApplication app(argc,argv);

QQmlApplicationEngine engine;

engine.load(QUrl("qrc://main.qml"));


QObject *root=NULL;

Qlist<QObject *>rootObjects=engine.rootObjects();

int count=rootObjects.size();

for(int i=0;i<count;i++)

{

if(rootObjects.at(i)->objectName()=="rootObject")

{

root=rootObjects.at(i);

break;

}

}

QObject *quitButton=root->findChild<QTObject *>("quitButton");;

if(quitButton!=NULL)

{

  QObject::connect(quitButton,SIGNAL(clicked()),&app,SLOT(quit());

}

QObject *textLabel=root->findChild<QObject *>("textLabel");

if(textLabel)

{

bool bRet=QMetaObject::invokeMethod(textLabel,"setText",q_ARG(QString,"world hello"));


textLabel->setProperty("color",QColor::fromRgb(255,0,0));

bRet=QMetaObect:::invokeMethod(textLabel,"doLayout");

}


Top