news 2026/1/31 18:31:47

QML中关联C++ Model 类的两种核心方式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
QML中关联C++ Model 类的两种核心方式

QML 中关联 C++ Model 类的两种核心方式:import 和 setContextProperty。

这两种方式的本质区别在于 Model 的提供者和作用域。

方式一:注册为 QML 类型并 Import 使用

这种方式是将 C++ 类注册到 QML 类型系统中,使其在 QML 中像一个内置类型一样被使用。

实现步骤:

  1. 在 C++ 中注册类型:使用 qmlRegisterType 函数将你的 Model 类注册为一个可在 QML 中实例化的类型。
  2. 在 QML 中 Import:在使用该 Model 的 QML 文件中,通过 import 语句导入其所在的模块。
  3. 在 QML 中声明实例化:像使用 Rectangle、Text 等元素一样,直接使用注册的类名来创建对象。

代码示例:

C++ 部分 (main.cpp 或某个初始化文件)

#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> // 假设你的 Model 类头文件 #include "mystringlistmodel.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; // 关键步骤:将 MyStringListModel 注册为 QML 类型 // 参数:<模块名(如MyApp)>、<主版本号>、<次版本号>、<QML中的类型名> qmlRegisterType<MyStringListModel>("MyModels", 1, 0, "MyStringListModel"); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); }

C++ Model 类 (mystringlistmodel.h/cpp)
这里以一个简单的字符串列表模型为例。

// mystringlistmodel.h #ifndef MYSTRINGLISTMODEL_H #define MYSTRINGLISTMODEL_H #include <QAbstractListModel> #include <QStringList> class MyStringListModel : public QAbstractListModel { Q_OBJECT public: explicit MyStringListModel(QObject *parent = nullptr); // 必须重写的函数 int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; // 可选:如果需要可编辑,重写此函数 bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; Qt::ItemFlags flags(const QModelIndex &index) const override; // 自定义角色 enum Roles { NameRole = Qt::UserRole + 1, ColorRole }; Q_ENUM(Roles) // 将枚举暴露给 QML // 添加数据的方法 public slots: void addItem(const QString &name, const QString &color); private: QStringList m_names; QStringList m_colors; }; #endif // MYSTRINGLISTMODEL_H

(.cpp 文件实现略,重点是展示如何在 QML 中使用)

QML 部分 (main.qml)

import QtQuick 2.15 import QtQuick.Controls 2.15 import MyModels 1.0 // 导入我们注册的模块 ApplicationWindow { width: 400 height: 300 visible: true // 直接在 QML 中声明并实例化我们的 Model // 就像使用一个普通的 QML Item 一样 MyStringListModel { id: stringModel // 可以在这里直接调用其槽函数来初始化数据 Component.onCompleted: { addItem("Apple", "red") addItem("Banana", "yellow") addItem("Grape", "purple") } } ListView { anchors.fill: parent model: stringModel // 将 ListView 的 model 设置为这个实例 delegate: Rectangle { width: ListView.view.width height: 40 color: model.color // 使用我们在 C++ 中定义的 ColorRole Text { text: model.name // 使用 NameRole anchors.centerIn: parent } } } }

特点与适用场景:

• 特点:

◦ 模块化:Model 成为 QML 环境的一部分,可以被任何导入相应模块的 QML 文件使用。 ◦ 封装性好:Model 的创建和配置逻辑可以完全放在 QML 端。 ◦ 可复用性高:同一个 Model 类可以在多个地方被实例化。 ◦ 类型安全:在编译时就能检查类型错误(如果工具支持)。

• 适用场景:

◦ 通用的、可复用的 Model 组件。 ◦ 希望将 Model 的创建和生命周期管理完全交给 QML 的场景。 ◦ 构建大型的、模块化的 QML 应用程序。

方式二:使用 setContextProperty

这种方式是在 C++ 端将一个已经创建好的 QObject 派生类(包括 Model)实例设置为 QML 引擎的上下文属性,使其在整个 QML 上下文中可用。

实现步骤:

  1. 在 C++ 中创建实例:在 C++ 代码中(通常是 main 函数中),创建你的 Model 类的实例。
  2. 设置上下文属性:使用 QQmlEngine::rootContext()->setContextProperty() 将这个实例注册为一个全局可用的 QML 对象。
  3. 在 QML 中直接使用:在 QML 中,可以直接使用你设置的名称来访问这个对象,无需 import。

代码示例:

C++ 部分 (main.cpp) #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "mystringlistmodel.h" // 同样的 Model 类 int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; // 1. 在 C++ 端创建 Model 实例 MyStringListModel stringModel; // 可以添加一些初始数据 // stringModel.addItem(...); // 2. 关键步骤:将实例设置为上下文属性 // 参数:<在QML中使用的名称>, <C++对象的指针> engine.rootContext()->setContextProperty("myCppModel", &stringModel); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); }

QML 部分 (main.qml)

import QtQuick 2.15 import QtQuick.Controls 2.15 // 注意:这里没有 ‘import MyModels 1.0’ ApplicationWindow { width: 400 height: 300 visible: true // 注意:没有在 QML 中声明 MyStringListModel // 它已经在 C++ 中被创建好了 ListView { anchors.fill: parent // 3. 直接使用在 C++ 中设置的上下文属性名 ‘myCppModel’ model: myCppModel delegate: Rectangle { width: ListView.view.width height: 40 color: model.color Text { text: model.name anchors.centerIn: parent } } } // 甚至可以在 Button 的 onClicked 中直接调用 C++ Model 的方法 Button { text: "Add Item" anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter onClicked: { // 直接调用 C++ 对象的槽函数 myCppModel.addItem("New Fruit", "green") } } }

特点与适用场景:

• 特点:

◦ 简单直接:对于单个实例或单例模式的 Model 非常方便。 ◦ 控制权在 C++:Model 的生命周期由 C++ 控制,通常在整个应用运行期间都存在。 ◦ 全局可用:一旦设置,在所有导入了该上下文的 QML 文件中都可以访问。 ◦ 无需注册类型:不需要使用 qmlRegisterType,代码稍简洁一些。

• 适用场景:

◦ 应用程序的全局状态管理(如用户数据、配置信息)。 ◦ 单例服务或管理器类。 ◦ 需要与 C++ 深度交互、且只有一个实例的 Model。 ◦ 快速原型开发或小型项目。

对比总结

特性 注册类型 (qmlRegisterType) 设置上下文属性 (setContextProperty)

提供者 QML 引擎的类型系统 QML 引擎的根上下文

使用方式 import + 声明式实例化 直接使用属性名

生命周期 QML 垃圾回收机制管理 C++ 端管理(通常是长期存在)

作用域 模块内可见 整个 QML 上下文可见(全局)

复用性 高,可创建多个实例 低,通常只有一个实例

灵活性 高,可在 QML 中任意创建和配置 较低,实例化和配置主要在 C++

典型用例 可复用的 UI 组件、通用 Model 全局状态、单例服务、管理器

如何选择?

• 如果你的 Model 是数据驱动的、需要被多个视图复用、或者其行为和创建逻辑更适合在 QML 中描述,请选择 注册类型。

• 如果你的 Model 代表一个全局的、单一的应用程序状态或服务,并且其生命周期应该由 C++ 牢牢掌控,请选择 设置上下文属性。

在实际项目中,这两种方式常常结合使用。例如,使用上下文属性提供一个全局的配置 Model,同时使用注册类型为不同的列表页面提供特定的数据 Model。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/28 3:02:02

Open-AutoGLM vs 竞品:谁才是长链路AI任务处理的真正王者?

第一章&#xff1a;Open-AutoGLM 长链路任务处理竞品比拼在长链路自动化任务处理领域&#xff0c;Open-AutoGLM 凭借其模块化架构与动态推理能力&#xff0c;展现出显著优势。面对如 AutoGPT、LangChain 和 BabyAGI 等主流框架的竞争&#xff0c;Open-AutoGLM 在任务分解精度、…

作者头像 李华
网站建设 2026/1/27 20:34:34

Web安全测试

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 随着互联网时代的蓬勃发展&#xff0c;基于Web环境下的应用系统、应用软件也得到了越来越广泛的使用。目前&#xff0c;很多企业的业务发展都依赖于互联网&…

作者头像 李华
网站建设 2026/1/31 3:55:42

【干货收藏】企业AI架构实战指南:从框架搭建到场景落地的底层逻辑

企业AI架构可分为五层&#xff1a;硬件层、数据层、模型层、AI应用插件层和应用层。部署方式需根据业务需求选择云端、本地或混合部署。架构规划应遵循三个原则&#xff1a;对齐业务、数据底座扎实、部署方式匹配需求。企业AI落地的关键是"用对的架构解决对的问题"&a…

作者头像 李华
网站建设 2026/1/27 22:47:51

13、FPGA更新与可编程性:安全与应用解析

FPGA更新与可编程性:安全与应用解析 1. 引言 与专用集成电路(ASIC)不同,静态随机存取存储器(SRAM)现场可编程门阵列(FPGA)在制造后能够改变其逻辑配置。定义该逻辑的比特流存储在非易失性片外存储器中,并在FPGA上电时加载到FPGA上。这种特性十分有用,若在逻辑设计中…

作者头像 李华