700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > C++与QML混合编程技术(传递自定义数据类型)

C++与QML混合编程技术(传递自定义数据类型)

时间:2024-02-06 15:22:19

相关推荐

C++与QML混合编程技术(传递自定义数据类型)

目录

一、前言

二、C++与QML集成的基础

2.1 语言特征

2.2 可集成的前提条件

2.3 基础数据类型

2.4 自定义数据类型

三、实例讲解

3.1 QML获取C++类的自定义结构体数据

3.1.1 结构体类型

3.1.2 配置数据类

3.1.3 配置信息管理类

3.1.4 向QML元对象系统注册自定义类

3.1.5 QML调用C++函数后得到自定义结构体数据

3.2 C++类接收QML传递的自定义数据

3.2.1 传递QML数组保存自定义数据

3.2.2 C++类解析QML数组数据

总结

一、前言

界面代码与逻辑代码分离困扰过许多软件开发人员,使用C++与QML混合编程在一定程序上解决上这个问题,但由于它们之间的数据类型不完全兼容,对于一些复杂数据的传递(例如:结构体数据),则需要重点关注和解决,本文结合自己的实践经验分享出解决方案。

二、C++与QML集成的基础

2.1 语言特征

C++的三个主要特征:

封装;继承;多态;

QML的两个主要特征:

描述用户界面的一种陈述性语言;支持javacript形式的编程控制;

2.2 可集成的前提条件

Qt元对象系统是Qt 类库独有的功能,是Qt对标准C++的扩展,它提供了三个功能:

对象之间通信机制(信号与槽);运行时类型信息;动态属性;

实现元对象,要满足三个条件:

该类必须继承自QObject类;类的私有区域声明Q_OBJECT宏,用于启动元对象特性,使用动态特性,信号和槽;元对象编译器(moc)为每个QObject子类,提供了实现元对象特性必须的代码 ;

由于QML引擎与Qt元对象系统的集成,可以从QML中访问任何从QObject继承的类的属性、方法和信号,C++代码既可以在应用中集成,也可以在插件中集成。

QML访问C++数据主要有三种方法:

将C++ 类的属性暴露给QML;从C++ 定义QML类型;用Context属性在QML中嵌入C++对象;

2.3 基础数据类型

C++和QML能自动转化部分常用的基础数据类型大约有16种,清单如下:

2.4 自定义数据类型

16种基础数据类型以外的其它数据类型是QML所无法识别的,可将它定义为复杂数据类型,结构体数据类型属于复杂数据类型中的一种。由于QObject子类都可以注册为QML对象类型,所以构造结构体对应的自定义类来与QML交互是可行的。

三、实例讲解

本人参与的开源项目iCupBox就应用了C++与QML混合编程,使用自定义结构体数据来代表配置信息项,通过自定义结构体数据的传递,实现数据配置的加载和保存。

3.1 QML获取C++类的自定义结构体数据

3.1.1 结构体类型

根据喝水提醒功能业务的需求,分析得到要配置的自定义结构体“ST_CFG_WATER_CLOCK”。

typedef struct ST_CFG_WATER_CLOCK {int nWaitingInterval;int nReminderTimes;int nTwinkle;ST_CFG_BASIC() {nWaitingInterval = 0;nReminderTimes = 0;nTwinkle = 0;}}CFG_WATER_CLOCK;

3.1.2 配置数据类

声明喝水提醒功能类(config_ini.h文件)

设置Q_PROPERTY宏,C++中的变量与QML的属性建立绑定。

class WaterClock : public QObject{Q_OBJECTQ_PROPERTY(int waitingInterval READ getWaitingInterval WRITE setWaitingInterval)Q_PROPERTY(int reminderTimes READ getReminderTimes WRITE setReminderTimes)Q_PROPERTY(int twinkle READ getTwinkle WRITE setTwinkle)public:explicit WaterClock(QObject *parent = 0);~WaterClock();int getWaitingInterval() const;int getReminderTimes() const;int getTwinkle() const;void setWaitingInterval(int);void setReminderTimes(int);void setTwinkle(int);private:int m_nWaitingInterval;int m_nReminderTimes;int m_nTwinkle;};

实现喝水提醒功能类(config_ini.cpp文件)

#include "config_ini.h"WaterClock::WaterClock(QObject *parent){}WaterClock::~WaterClock(){}int WaterClock::getWaitingInterval() const{return m_nWaitingInterval;}int WaterClock::getReminderTimes() const{return m_nReminderTimes;}int WaterClock::getTwinkle() const{return m_nTwinkle;}void WaterClock::setWaitingInterval(int nWaitingInterval){m_nWaitingInterval = nWaitingInterval;}void WaterClock::setReminderTimes(int nReminderTimes){m_nReminderTimes = nReminderTimes;}void WaterClock::setTwinkle(int nTwinkle){m_nTwinkle = nTwinkle;}

3.1.3 配置信息管理类

声明配置信息管理类(config_mgr.h)

设置Q_INVOKABLE宏,C++中的函数允许被QML调用。

#ifndef CONFIG_MGR_H#define CONFIG_MGR_H#include <QQuickItem>#include "config_ini.h"class ConfigMgr : public QQuickItem{Q_OBJECTpublic:explicit ConfigMgr(QQuickItem *parent = 0);~ConfigMgr() override;public:Q_INVOKABLE WaterClock *loadWaterClockInfo();Q_INVOKABLE bool saveWaterClockInfo(const QVariantList &lstWaterClock);};#endif // CONFIG_MGR_H

实现配置信息管理类(config_mgr.cpp)

#include "config_mgr.h"#include <QDebug>ConfigMgr::ConfigMgr(QQuickItem *parent):QQuickItem(parent){// By default, QQuickItem does not draw anything. If you subclass// QQuickItem to create a visual item, you will need to uncomment the// following line and re-implement updatePaintNode()// setFlag(ItemHasContents, true);Q_ASSERT(NULL != ConfigINI::GetInstance(this));qDebug() << Q_FUNC_INFO;}ConfigMgr::~ConfigMgr(){qDebug() << Q_FUNC_INFO;}WaterClock *ConfigMgr::loadWaterClockInfo(){qDebug() << Q_FUNC_INFO;// Read data from INIST_CFG_WATER_CLOCK stCfgWaterClock;ConfigINI::GetInstance(this)->ReadIni(stCfgWaterClock);// Assign value from structure to objectWaterClock *pWaterClock = new WaterClock();pWaterClock->setWaitingInterval(stCfgWaterClock.nWaitingInterval);pWaterClock->setReminderTimes(stCfgWaterClock.nReminderTimes);pWaterClock->setTwinkle(stCfgWaterClock.nTwinkle);return pWaterClock;}bool ConfigMgr::saveWaterClockInfo(const QVariantList &lstWaterClock){qDebug() << Q_FUNC_INFO << lstWaterClock.size();if(3 != lstWaterClock.size()) return false;// Assign value from variant to structureST_CFG_WATER_CLOCK stCfgWaterClock;stCfgWaterClock.nWaitingInterval = lstWaterClock[0].toInt();stCfgWaterClock.nReminderTimes = lstWaterClock[1].toInt();stCfgWaterClock.nTwinkle = lstWaterClock[2].toInt();// Write data into INIConfigINI::GetInstance(this)->WriteIni(stCfgWaterClock);return true;}

3.1.4 向QML元对象系统注册自定义类

使用qmlRegisterType,将自定义的QObject派生类注册到QML,它是连接C++和QML的工具。

#include "ipluginsmgr_plugin.h"#include "config/config_mgr.h"#include <qqml.h>void IPluginsMgrPlugin::registerTypes(const char *uri){// @uri com.mycompany.qmlcomponents// Register class types to QMLqmlRegisterType<WaterClock>(uri, 1, 0, "WaterClock");qmlRegisterType<ConfigMgr>(uri, 1, 0, "ConfigMgr");}

3.1.5 QML调用C++函数后得到自定义结构体数据

QML及C++插件项目的文件分布如下:

main.qml文件

import QtQuick 2.5import QtQuick.Window 2.2import com.mycompany.qmlcomponents 1.0Window {id: wndRootvisible: truewidth: 1000height: 800title: qsTr("iCupBox v1.0.0")MainForm {anchors.fill: parent}ConfigMgr {id: cppConfigMgr}}

WaterClockView.qml文件

Component.onCompleted: {// Load default parameter datavar pWaterClock = cppConfigMgr.loadWaterClockInfo()console.log("cmb_waiting_time::onCompleted " + pWaterClock.waitingInterval, pWaterClock.reminderTimes, pWaterClock.twinkle)cmb_waiting_time.currentIndex = pWaterClock.waitingInterval;cmb_reminder_times.currentIndex = pWaterClock.reminderTimes;cmb_twinkle.currentIndex = pWaterClock.twinkle;}

3.2 C++类接收QML传递的自定义数据

3.2.1 传递QML数组保存自定义数据

在QML中的使用信号-槽来收集页面上的配置信息数据后,使用var数据的形式暂时存储,再将其传递给C++类。

import QtQuick 2.0import QtQuick.Layouts 1.1import QtQuick.Controls 1.4Item {signal currentIndexChanged()function onHandleCurrentIndexChanged() {// Get the change value of the indexvar arrWaterClock = []arrWaterClock.push(cmb_waiting_time.currentIndex)arrWaterClock.push(cmb_reminder_times.currentIndex)arrWaterClock.push(cmb_twinkle.currentIndex)// Modify default parameter datavar result = cppConfigMgr.saveWaterClockInfo(arrWaterClock)console.log("onHandleUpdateWaterClock ",result)}...ComboBox {id: cmb_waiting_timeheight: 25Layout.minimumWidth: 100model:[qsTr("25 minutes"), qsTr("50 minutes"), qsTr("75 minutes"), qsTr("100 minutes")]Component.onCompleted: {currentIndexChanged.connect(onHandleCurrentIndexChanged)}onActivated: {currentIndex = indexconsole.log("cmb_waiting_time::onActivated",currentIndex)// The index is changed, and the default configuration is updatedcurrentIndexChanged()}}}

3.2.2 C++类解析QML数组数据

在config_mgr.cpp类中处理QML数据。

bool ConfigMgr::saveWaterClockInfo(const QVariantList &lstWaterClock){qDebug() << Q_FUNC_INFO << lstWaterClock.size();if(3 != lstWaterClock.size()) return false;// Assign value from variant to structureST_CFG_WATER_CLOCK stCfgWaterClock;stCfgWaterClock.nWaitingInterval = lstWaterClock[0].toInt();stCfgWaterClock.nReminderTimes = lstWaterClock[1].toInt();stCfgWaterClock.nTwinkle = lstWaterClock[2].toInt();// Write data into INIConfigINI::GetInstance(this)->WriteIni(stCfgWaterClock);return true;}

总结

C++与QML混合编程就是优势互补的编程策略,使用QML高效便捷地构建UI,使用C++实现业务逻辑和复杂算法。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。