C++调用QML实际上就是通过 QML 对象的指针去访问QML对象的属性和方法
只要获取到QML对象的指针,接下来就和普通C++代码调用一样
QML中的类,其实都是继承与QObject,Qt类在构建的过程中是有对象树,每个对象都有父对象和子对象,调用对应的方法就很容易获取到
获取到QML对象指针后,主要是通过这几个方法 访问 QML的
QT开发交流+赀料君羊:661714027
QT开发交流+赀料君羊:661714027
QVariant QObject::property(const char *name) const // 访问变量
bool QObject::setProperty(const char *name, const QVariant &value) // 设置变量的值
QMetaObject::invokeMethod // 调用方法
1.QML 代码
import QtQuick 2.0
import QtQuick.Window 2.2
Rectangle {
width: 500
height: 400
// 测试传数组
ListView {
id: listView
model : ListModel {
id: myModel
}
width: 100
height: 400
delegate: Rectangle{
height: 20
width: 100
color : "#9bee95"
Text {
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
text: val //访问model 中的数据
}
}
}
Rectangle {
id : rect
objectName: "rect"
anchors.centerIn: parent
width: 100
height: 100
color: "#00ffffff"
border.color: "#19e8d0"
border.width: 5
radius: 10
// 定义一个变量,让C++访问
property bool isShow: visible
// 定义一个方法,让C++调用
function rotateToAngle(angle) {
rotation = angle
return true
}
function buttonClicked(){
console.log("按钮被点击")
}
// 接收复杂类型
function reciveComplexType( comp ) {
var obj = JSON.parse(comp)
console.log(obj.name)
console.log(obj.val)
myModel.clear();
for (var i=0; i < obj.arr.length; ++i)
myModel.append({"val" : obj.arr[i] })
}
Text {
id: text
objectName: "text"
text : "C++调用QML";
anchors.centerIn: parent
}
}
}
- C++要调用的对象要设置objectName,否则无法获取到QML对象的指针
- property bool isShow: visible C++中访问 isShow 变量
- function rotateToAngle(angle) C++中调用 rotateToAngle 方法,传一个float类型
- function buttonClicked() C++中调用 buttonClicked 方法
- function reciveComplexType( comp ) C++中传递一个json字符串过来,QML中解析json数据
2. C++/Qt 代码
- 主函数代码
int main(int argc, char **argv)
{
QApplication a(argc, argv);
// 显示QML界面
QQuickView view;
view.setSource(QUrl::fromLocalFile( "../Cpp_Call_QML/main.qml"));
view.show();
// 初始化QML根节点
QMLObj::instance().initQMLRootObj(view.rootObject());
// 模拟C++调用QML
Cpp c;
c.show();
return a.exec();
}
- 这里调用 QMLObj::instance().initQMLRootObj(view.rootObject()); 将QML的根元素存了起来,为了找他的子对象
QMLObj类代码
#pragma once
#include <QHash>
#include <QObject>
#include <QQuickItem>
class QMLObj
{
QMLObj() : rootItem(nullptr) {}
public:
static QMLObj &instance()
{
static QMLObj obj;
return obj;
}
void initQMLRootObj(QObject * rootItem)
{
this->rootItem = rootItem;
}
QObject * getQMLObject(const QString objName)
{
if (qmlObjs.find(objName) != qmlObjs.end())
{
return qmlObjs[objName];
}
else if (rootItem)
{
QObject *obj = rootItem->findChild<QObject *>(objName);
if (!obj) return nullptr;
qmlObjs[objName] = obj;
return obj;
}
else
{
return nullptr;
}
}
private:
QHash<QString, QObject *> qmlObjs;
QObject *rootItem;
};
这个类就是为了获取QML对象的指针,只要拿到指针就好办了
因为不知道怎么获取QML全局的root对象,所以就从main函数中把rootObject传给这个类做初始化,QML不像QApplication,QApplication可以直接调用静态方法 instance() 获取实例。
C++调用代码
#include "Cpp.h"
#include <QPushButton>
#include <QDebug>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QMetaObject>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
#include <QHBoxLayout>
#include "QMLObj.h"
Cpp::Cpp(QWidget *parent) : QWidget(parent)
{
QPushButton * bt1 = new QPushButton("访问isShow", this);
QPushButton * bt2 = new QPushButton("调用 rotateToAngle", this);
QPushButton * bt3 = new QPushButton("调用 buttonClicked", this);
QPushButton * bt4 = new QPushButton("调用 reciveComplexType", this);
QHBoxLayout * layout = new QHBoxLayout;
this->setLayout(layout);
layout->addWidget(bt1);
layout->addWidget(bt2);
layout->addWidget(bt3);
layout->addWidget(bt4);
connect(bt1, &QPushButton::clicked, []{
QObject *rect = QMLObj::instance().getQMLObject("rect");
if (rect)
{
qDebug() << rect->property("isShow").toBool();
}
} );
connect(bt2, &QPushButton::clicked, []{
QObject *rect = QMLObj::instance().getQMLObject("rect");
if (rect)
{
QVariant ok = false;
QMetaObject::invokeMethod(rect, "rotateToAngle", Q_RETURN_ARG(QVariant, ok), Q_ARG(QVariant, 60));
}
});
connect(bt3, &QPushButton::clicked, [] {
QObject *rect = QMLObj::instance().getQMLObject("rect");
if (rect)
{
QMetaObject::invokeMethod(rect, "buttonClicked");
}
});
connect(bt4, &QPushButton::clicked, []{
QObject *rect = QMLObj::instance().getQMLObject("rect");
if (rect)
{
// 复杂数据类型
QJsonObject jsObj;
jsObj["name"] = "复杂数据类型";
jsObj["val"] = 12345;
QJsonArray arr;
arr.append("复");
arr.append("杂");
arr.append("数");
arr.append("据");
jsObj["arr"] = arr;
QMetaObject::invokeMethod(rect, "reciveComplexType", Q_ARG(QVariant, QJsonDocument(jsObj).toJson()));
}
});
}
bt1 访问 rect 的 isShow 的属性
bt2 调用 rect 的 rotateToAngle 方法,让矩形旋转
bt3 调用 rect 的 buttonClicked方法,在QML中输出日志
bt4 调用 rect 的 reciveComplexType 方法,传递复杂类型给QML,其实就是一个JSON字符串,然后在QML中解析JSON字符串,获取里面的数据
3. 运行效果
原文作者:亿速云
原文地址:https://www.jianshu.com/p/3fac2b1d33af