您现在的位置是:网站首页> 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");
}
下一篇:QML学习体会