当前位置: 首页 > news >正文

QML学习笔记(五十四)QML与C++交互:数据转换——QVariantList与QVariantMap

前言

之前已经介绍了基本数据类型、时间和日期、序列数组的转换,除此之外还有一种QVariantListQVariantMap的转换,熟悉QVariant的朋友应该知道,它是 Qt 框架中的一个通用数据类型,用于存储多种数据类型值,如基本类型QStringQWidget等。它通过类型擦除实现,内部维护一个类型标识器来识别存储的数据类型,并支持类型转换。QVariantList 是存储 QVariant 的线性列表,支持动态扩展,允许存储不同类型的值。QVariantMap 则是键值对的存储形式,键为 QString,值为 QVariant,同样支持存储多种类型值。需要注意的是,QVariant 支持的类型需通过 Q_DECLARE_METATYPE 注册,以确保正确存储和转换。
而本节示例的就是C++到QML的QVariantList与QVariantMap转换。

一、代码示例

基于之前的工程,我们添加一个新的类:

#ifndef CPPCLASS1_H
#define CPPCLASS1_H#include <QObject>
#include <QtQml>
#include <QColor>
#include <QFont>class CppClass1 : public QObject
{Q_OBJECT
public:explicit CppClass1(QObject *parent = nullptr);Q_INVOKABLE void passFromQmlToCpp(QVariantList list, QVariantMap map);Q_INVOKABLE QVariantList getVariantListFromCpp();Q_INVOKABLE QVariantMap getVariantMapFromCpp();void setQmlRootObject(QObject *value);signals:public slots:void triggerJsCall();private:QObject * qmlRootObject;};#endif // CPPCLASS1_H
#include "cppclass1.h"CppClass1::CppClass1(QObject *parent): QObject{parent}
{}
void CppClass1::passFromQmlToCpp(QVariantList list/*array*/, QVariantMap map/*object*/)
{qDebug() << "Received variant list and map from QML";qDebug() << "List :";for( int i{0};i < list.size();i++){qDebug() << "List item :" << list.at(i).toString();}qDebug() << "Map :";for( int i{0};i < map.keys().size();i++){qDebug() << "Map item :" << map[map.keys().at(i)].toString();}
}QVariantList CppClass1::getVariantListFromCpp()
{QVariantList list;list << 123.3 << QColor(Qt::cyan) << "Qt is great" << 10;return list;
}QVariantMap CppClass1::getVariantMapFromCpp()
{QVariantMap map;map.insert("movie","Game of Thrones");map.insert("names","John Snow");map.insert("role","Main Character");map.insert("release", QDate(2011, 4, 17));return map;
}void CppClass1::setQmlRootObject(QObject *value)
{qDebug()<<"setQmlRootObject";qmlRootObject = value;
}void CppClass1::triggerJsCall()
{qDebug() << "Calling JS";QVariantList list;//arraylist << 123.3 << QColor(Qt::cyan) << "Qt is great" << 10;QVariantMap map;//objectmap.insert("movie","Game of Thrones");map.insert("names", "John Snow");map.insert("role","Main Character");map.insert("release", QDate(2011, 4, 17));QMetaObject::invokeMethod(qmlRootObject,"arrayObjectFunc",Q_ARG(QVariant, QVariant::fromValue(list)),Q_ARG(QVariant,QVariant::fromValue(map)));qDebug() << "Called JS";
}

这里介绍一下几个接口的作用:
1.passFromQmlToCpp:顾名思义,传递qml端的参数到C++端进行打印,接口的参数是QVariantList和QVariantMap,对应qml端的话是array和object的概念,这一点在之后的qml代码中有所呈现。
2.getVariantListFromCpp:从c++端获取一个QVariantList,可以看到传入这个list的数据类型可以是不同的:

list << 123.3 << QColor(Qt::cyan) << "Qt is great" << 10;

3.getVariantMapFromCpp:从c++端获取一个QVariantMap,可以看到传入这个的数据类型可以是不同的,但键值需要时字符串:

QVariantMap map;
map.insert("movie","Game of Thrones");
map.insert("names","John Snow");
map.insert("role","Main Character");
map.insert("release", QDate(2011, 4, 17));

4.setQmlRootObject:设置qml的根对象,我们需要在main中专门设置这个,这样才能在C++中直接调用qml侧的代码:
5.triggerJsCall:C++侧直接调用qml的接口arrayObjectFunc,传递QVariantList和QVariantMap两个参数。

然后,我们看main代码:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <cppclass.h>
#include <cppclass1.h>int main(int argc, char *argv[])
{QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QGuiApplication app(argc, argv);QQmlApplicationEngine engine;CppClass1 cppclass1;engine.rootContext()->setContextProperty("CppClass1",&cppclass1);const QUrl url(QStringLiteral("qrc:/main.qml"));QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,&app, [url](QObject *obj, const QUrl &objUrl) {if (!obj && url == objUrl)QCoreApplication::exit(-1);}, Qt::QueuedConnection);engine.load(url);if(engine.rootObjects().isEmpty()){qDebug()<<"engine.rootObjects().isEmpty()";return -1;}else{cppclass1.setQmlRootObject(engine.rootObjects().first());}return app.exec();
}

这里创建了一个cppclass1对象,并上下文暴露给qml侧。最重要是它还设置了qml的根对象。
然后是qml侧:

function arrayObjectFunc(array,object){console.log("---Printing array---")array.forEach(function(element){console.log("Array item :"+ element)})console.log("---Printing object---")for (var mkey in object){console.log("Object["+mkey+"]:"+ object[mkey])}}Button{id :button1anchors.left: button2Id.righttext : "Pass data to Cpp"onClicked:{var arr = ['Africa','Asia',"Europe","North America","South America","Oceania","Antarctica"]var obj={firstName:"John",lastName:"Doe",location:"Earth"}CppClass1.passFromQmlToCpp(arr,obj);// cppClassId.passFromQmlToCpp(arr,obj);}}Button{id :button2anchors.top : button1.bottomx : button1.xtext :"GetVariantListFromCpp"onClicked:{var data = CppClass1.getVariantListFromCpp() //returns arraydata.forEach(function(element){console.log("Array item:" + element)})}}Button{id : button3anchors.top : button2.bottomx : button2.xtext :"GetVariantMapFromCpp"onClicked:{var data = CppClass1.getVariantMapFromCpp() //returns objectfor ( var mKey in data){console.log("Object[" +mKey+"] :"+ data[mKey])}}}Button {id : button4text : "TriggerJSCall"anchors.top: button3.bottomx : button2.xonClicked:{CppClass1.triggerJsCall();}}

这里首先设置了一个JS函数arrayObjectFunc,里面可以打印list和map的参数。

二、演示效果

qml中主要设置了四个按钮,作用分别是:
1.向C++传入qml的数组和对象,在c++中打印QVariantList与QVariantMap
2.qml从C++获取QVariantList,并打印数据
3.qml从C++获取QVariantMap,并打印数据
4.触发C++函数,让其调用qml侧的函数,并最终打印数据
看下效果:
在这里插入图片描述
依次点击,打印:
1.

Received variant list and map from QML
List :
List item : "Africa"
List item : "Asia"
List item : "Europe"
List item : "North America"
List item : "South America"
List item : "Oceania"
List item : "Antarctica"
Map :
Map item : "John"
Map item : "Doe"
Map item : "Earth"
qml: Array item:123.3
qml: Array item:#00ffff
qml: Array item:Qt is great
qml: Array item:10
qml: Array item:123.3
qml: Array item:#00ffff
qml: Array item:Qt is great
qml: Array item:10
Calling JS
qml: ---Printing array---
qml: Array item :123.3
qml: Array item :#00ffff
qml: Array item :Qt is great
qml: Array item :10
qml: ---Printing object---
qml: Object[movie]:Game of Thrones
qml: Object[names]:John Snow
qml: Object[release]:Sun Apr 17 08:00:00 2011 GMT+0800
qml: Object[role]:Main Character
Called JS

可以看到,这些数据的传输都没有什么大问题。唯一一个是颜色,传递的是QColor,解析出来是#00ffff,可能被当做了字符串,当然直接拿来使用也没有问题。

三、总结

QVariantList与QVariantMap虽然不那么常用,但能很好的批量传递一些参数和信息,这在某些设计方式中可能有帮助。
至此,我们应该能很好地处理C++和qml之间的数据类型转换了。

http://www.dtcms.com/a/585205.html

相关文章:

  • Linux的基础IO流
  • RabbitMQ死信交换机与延迟队列:原理、实现与最佳实践
  • 网站建设人员叫什么科目wordpress站长地图
  • Kafka安装搭建
  • 深度血虚:Django水果检测识别系统 CNN卷积神经网络算法 python语言 计算机 大数据✅
  • 郑州h5网站建设信息流推广
  • Git-新建分支并推送远程仓
  • 团关系转接网站建设免费psd模板素材
  • 永磁同步电机MTPA控制详解:从理论到实践的全方位指南
  • 【GORM(3)】Go的跨时代ORM框架!—— 数据库连接、配置参数;本文从0开始教会如何配置GORM的数据库
  • AIStarter 服务器版 PanelAI 开源+早鸟票 抢商业永久授权
  • 【项目】pyqt5基于python的照片整蛊项目
  • 深入理解Java堆栈:从原理到面试实战
  • MySQL快速入门——基本查询(下)
  • PyTorch深度学习进阶(二)(批量归一化)
  • 基于字符串的专项实验
  • CPO-SVM回归 基于冠豪猪优化算法支持向量机的多变量回归预测 (多输入单输出)Matlab
  • 飞凌嵌入式ElfBoard-标准IO接口之关闭文件
  • Rust 练习册 :Prime Factors与质因数分解
  • 12380网站开发apache wordpress rewrite
  • CSS - transition 过渡属性及使用方法(示例代码)
  • web网页开发,在线%考试管理%系统,基于Idea,vscode,html,css,vue,java,maven,springboot,mysql
  • 2025年北京海淀区中小学生信息学竞赛第一赛段试题(附答案)
  • Linux 基础开发工具入门:软件包管理器的全方位实操指南
  • 金仓数据库用户权限隔离:从功能兼容到安全增强的技术演进
  • shell(4)--shell脚本中的循环:(if循环,for,while,until)和退出循环(continue,break, exit)
  • IDEA 软件下载 + 安装 | 操作步骤
  • seo建站推广泉州建站软件
  • HarmonyOS 诗词填空游戏开发实战教程(非AI生成 提供源代码和演示视频)
  • 【期末网页设计作业】HTML+CSS+JavaScript 蜡笔小新 动漫主题网站设计与实现(附源码)