0


【C++/QML】C++与QML交互方法(一)

前言

最近开始做新的项目开发,准备采用Qt框架,使用QML作为前端框架,用C++编写底层结构和算法,接触QML时间不长,用此篇文章记录一下C++代码与QML之间的交互方法,以供日后回顾查看与温习。

在我们新创建一个QuickApplication项目之后,我们的项目文件中存在两个初始文件,一个是main.cpp,另一个是main.qml。

图1 main.cpp文件

图2 main.qml文件

在main.cpp文件中我们可以看到两个不同类型的对象,一个是QGuiApplication类对象,一个是QQmlApplicationEngine类对象,这两个类都是Qt框架中用于处理应用程序生命周期和QML集成的类,但它们在Qt的不同模块中使用,并且有不同的用途和特点。

QGUIApplication

是Qt GUI模块中的一个类,主要用于传统的Qt Widgets应用程序。它继承自

QApplication

类,并添加了一些特定于图形用户界面应用程序的功能。以下是

QGUIApplication

的一些关键特点:

  • 管理应用程序的生命周期,包括初始化和退出。
  • 处理事件循环,响应用户输入和系统事件。
  • 可以与QML集成,但通常用于非QML的Widgets应用程序。
QQmlApplicationEngine

是Qt QML模块中的一个类,专门为QML应用程序设计。它提供了一个用于加载和执行QML代码的高级API。以下是

QQmlApplicationEngine

的一些关键特点:

  • 用于加载和运行QML文件。
  • 支持动态QML内容的加载,可以在运行时加载和卸载QML组件。
  • 提供了与QML集成的高级功能,如JavaScript和C++的绑定。
  • 可以访问QML中的属性和方法,实现QML与C++的双向通信。

QML和C++代码的通讯都是通过Qt Meta-Object System系统实现的,例如信号和槽的连接,属性的获取和修改、C++的槽函数或者被标记为Q_INVOKABLE的方法可以直接被QML调用以及QML可以直接获取Q_ENUM的枚举对象等。

因此QML和C++代码的整合可以通过几种方式实现:

  • 通过上下文属性,利用setContextProperty()方法;
  • 在qml引擎中注册类型,通过在main.cpp中调用qmlRegisterType
  • 使用QML扩展插件

接下来我们来介绍几种C++与QML交互方法

一、SetContextProperty()方法

实现通讯的最重要的一点是:QObjects对象需要被显示地暴露给QML运行时的上下文(QObjects(and value type objects) need to be explicitly exposed to the QML runtime context in order to be accesible),这其中最重要的关键类是QQmlContext

  • 在main.cpp文件的main函数中,我们创建一个QQmlContext对象context,并调用rootContext()指向了engine的根上下文,这个上下文包含了QML代码可以访问的所有初始属性和对象;
  • 调用context的成员函数setContextProperty(),将自定义的属性暴露给context;
  • 之后在main.qml文件中就可以使用qml创建对象,并使用刚才暴露给context的属性“myBackgroundColor"和“myText"的值

void **QQmlContext::setContextProperty(*const QString &name, QObject value)*方法会传入两个参数,一个是自定义属性的名称,一个是自定义属性的值,这个值是一个QObject对象,因此常见的类型都可以直接传入。

例如上图所示,你可以将QGuiApplication对象的指针传入,这样就可以在qml中调用相关的函数。

这个方法会作用于全局,一般来说用到的情况比较少

二、Q_PROPERTY()宏与qmlRegisterSingletonInstance()

上面提到了用setContextObject()方法将属性直接暴露给context,但是这种方式并不安全,也不便于内存管理,因此可以通过qt提供的另一种方法,将C++类暴露给QML进行使用。

首先,我们先创建一个自定义的类MyDataSet用来暴露给QML使用:

为了让该类与QML进行通讯,我们需要做一下几件事情:

  • 在类中声明Q_OBJECT宏,并继承QObject类,该宏非常重要,是qt框架元对象系统meta-object system的入口,能够让Qt的构建系统知道该类需要元对象编译器(moc:meta-object compiler)进行特殊处理;
  • 使用Q_PROPERTY宏创建需要暴露给QML的属性,该宏需要定义: - 属性类型和名称,读取器名称,写入器名称,属性改变通知信号名称。- 这其中还有一个特殊的关键字MEMBER,该关键字允许你为该属性设置一个字段,qt会自动生成读写该字段的读取器和写入器,建议不要与READ和WRITE一起使用,因此建议用法如下: - READ + WRITE,可读写,自己实现读写器- READ,只读,自己实现读取器- MEMBER,可读写,指定字段,自动实现读写器

完成自定义类和Q_PROPERTY的编写之后,我们就可以进行注册:

这里我们使用qmlRegisterSingletonInstance()方法,在qml中注册一个单例对象dataSet, 这样注册有以下的优点:

  1. 集中管理: 单例模式确保了一个类只有一个实例,并提供一个全局访问点。这使得状态和资源可以跨多个组件或对象共享。
  2. 生命周期控制: 单例的生命周期与应用程序的生命周期保持一致,不需要手动创建和销毁,降低了内存泄漏的风险。
  3. QML 访问: 通过注册单例,你可以在 QML 中直接访问该单例的属性和方法,而无需担心对象的创建和销毁。
  4. 类型安全: QML 引擎会在编译时检查单例的使用,确保只有正确的类型被访问,提高了代码的健壮性。
  5. 避免重复实例化: 单例确保了在整个应用程序中只有一个实例,避免了重复创建相同功能的多个实例。
  6. 跨组件共享: 单例可以在不同的组件之间共享,使得状态和行为可以在应用程序的多个部分中保持一致。
  7. 简化 QML 代码: 在 QML 中使用单例,可以避免复杂的对象创建和传递,简化了 QML 代码。
  8. 性能优化: 由于单例是在应用程序启动时创建的,并且持续存在,因此避免了每次需要时都创建新实例的开销。
  9. 更好的封装性: 单例模式隐藏了实现细节,只暴露出一个访问点,使得内部实现可以在不影响使用者的情况下进行更改。
  10. 易于维护和扩展: 当需要添加新功能或修改现有功能时,单例提供了一个清晰的路径来扩展或修改应用程序的行为。

注册完成之后我们就可以在QML中使用我们所注册的对象了:

标签: c++ 交互 开发语言

本文转载自: https://blog.csdn.net/weixin_43776810/article/details/139654358
版权归原作者 MajorTom33 所有, 如有侵权,请联系我们删除。

“【C++/QML】C++与QML交互方法(一)”的评论:

还没有评论