界面架构 - MVVM (Qt)

MVVM

  • MVVM 的主要特点
  • 示例
    • 示例功能
    • 示例代码
    • ViewModel 类(C++)
    • 主函数入口(main.cpp)
  • QML 文件(main.qml)
  • 总结

MVVM(Model-View-ViewModel)架构是一种旨在进一步分离界面和业务逻辑的设计模式,特别适合支持数据绑定的 UI 框架,如 Qt Quick(QML)。在 MVVM 架构中,主要包含以下三个部分:

  • Model(模型)
    与其他架构类似,Model 层负责数据存储和业务逻辑处理。在本例中,Model 的逻辑非常简单,就是计算字符串的长度。通常我们可以把这部分逻辑直接集成到 ViewModel 中,或者在更复杂的项目中将其独立出来。

  • View(视图)
    View 层负责界面展示和用户交互,通常只关心如何展示数据。通过数据绑定,View 可以自动响应 ViewModel 中数据的变化,而不需要手动更新界面。在 Qt Quick 中,View 通常由 QML 文件构成。

  • ViewModel(视图模型)
    ViewModel 层充当了 Model 与 View 之间的中介,它暴露 View 所需的数据和操作(通常以属性和方法的形式),并负责处理用户的交互逻辑。通过 Q_PROPERTY 与信号机制,ViewModel 可以将 Model 的数据转换为 View 可直接绑定的形式,从而实现自动同步更新。

MVVM 的主要特点

  • 数据绑定
    ViewModel 的属性与 View 通过数据绑定建立联系,当 ViewModel 中的数据发生变化时,View 会自动更新显示,减少了手动更新 UI 的代码。

  • 彻底解耦
    ViewModel 不依赖于 View 的具体实现,降低了耦合度,使得业务逻辑更容易单独测试和维护。

  • 增强的可测试性
    由于 ViewModel 是纯 C++ 类(或 QML 中的 JavaScript 对象),它可以独立于 UI 环境进行单元测试。

示例

示例功能

构建一个简单的应用,界面包含:

  • QLineEdit:供用户输入字符串;
  • QPushButton:当用户点击按钮时,计算 QLineEdit 中文本的字符数;
  • QLabel:显示计算后的字符数。

我们将使用 Qt Quick(QML)构建 View,并使用 C++ 实现 ViewModel 类,将业务逻辑(计算字符串长度)封装在 ViewModel 中。

示例代码

ViewModel 类(C++)

定义一个 ViewModel 类,包含两个属性:

  • inputText:用户输入的文本,支持读写;

  • result:计算结果,只读属性。当用户点击按钮时,调用 ViewModel 的槽函数计算输入文本长度,并更新 result 属性。

// ViewModel.h
#ifndef VIEWMODEL_H
#define VIEWMODEL_H#include <QObject>
#include <QString>class ViewModel : public QObject
{Q_OBJECTQ_PROPERTY(QString inputText READ inputText WRITE setInputText NOTIFY inputTextChanged)Q_PROPERTY(QString result READ result NOTIFY resultChanged)public:explicit ViewModel(QObject *parent = nullptr) : QObject(parent) {}QString inputText() const { return m_inputText; }void setInputText(const QString &text) {if (m_inputText != text) {m_inputText = text;emit inputTextChanged();}}QString result() const { return m_result; }public slots:// 当按钮点击时调用此槽,计算输入文本长度void calculateLength() {int len = m_inputText.length();m_result = QString("长度:%1").arg(len);emit resultChanged();}signals:void inputTextChanged();void resultChanged();private:QString m_inputText;QString m_result;
};#endif // VIEWMODEL_H

主函数入口(main.cpp)

在 main 函数中,我们创建 QGuiApplication 和 QQmlApplicationEngine,并将 ViewModel 实例通过上下文属性传递给 QML 层,供界面绑定和调用。

// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "ViewModel.h"int main(int argc, char *argv[])
{QGuiApplication app(argc, argv);QQmlApplicationEngine engine;// 创建 ViewModel 实例ViewModel viewModel;// 将 ViewModel 注册到 QML 上下文中,名字为 "viewModel"engine.rootContext()->setContextProperty("viewModel", &viewModel);engine.load(QUrl(QStringLiteral("qrc:/main.qml")));if (engine.rootObjects().isEmpty())return -1;return app.exec();
}

QML 文件(main.qml)

// main.qml
import QtQuick 2.12
import QtQuick.Controls 2.12ApplicationWindow {visible: truewidth: 300height: 200title: "MVVM 示例"Column {spacing: 10anchors.centerIn: parentTextField {id: inputFieldplaceholderText: "请输入文本"text: viewModel.inputTextonTextChanged: viewModel.inputText = text}Button {text: "计算长度"onClicked: viewModel.calculateLength()}Text {text: viewModel.resultfont.pointSize: 16}}
}

在 QML 中,我们构建一个简单的界面,包含一个 TextField、一个 Button 和一个 Text。

TextField 的文本与 viewModel.inputText 绑定;

Button 的点击事件调用 viewModel.calculateLength();

Text 的显示内容绑定到 viewModel.result。

总结

在上述 MVVM 示例中:

  • ViewModel 封装了业务逻辑(计算字符串长度),并通过 Q_PROPERTY 暴露输入文本(inputText)和计算结果(result)。当用户操作界面时,ViewModel 中的数据会更新,并通过信号通知 QML 自动刷新界面。

  • View(QML 部分) 仅负责界面展示和用户交互,通过数据绑定与 ViewModel 建立联系。这样 View 完全不关心具体的业务逻辑,降低了耦合度。

  • Model 部分在这个简单示例中直接内嵌在 ViewModel 中,但在更复杂的项目中,可以将业务逻辑和数据存储进一步独立出来。

这种架构充分利用了 QML 的数据绑定特性,使得界面和业务逻辑解耦,提升了代码的可维护性和可测试性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/899897.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第十四届MathorCup高校数学建模挑战赛-C题:基于 LSTM-ARIMA 和整数规划的货量预测与人员排班模型

目录 摘要 一、 问题重述 1.1 背景知识 1.2 问题描述 二、 问题分析 2.1 对问题一的分析 2.2 对问题二的分析 2.3 对问题三的分析 2.4 对问题四的分析 三、 模型假设 四、 符号说明 五、 问题一模型的建立与求解 5.1 数据预处理 5.2 基于 LSTM 的日货量预测模型 5.3 日货量预测…

银河麒麟V10 aarch64架构安装mysql教程

国产操作系统 ky10.aarch64 因为是arm架构&#xff0c;故选择mysql8&#xff0c;推荐安装8.0.28版本 尝试8.0.30和8.0.41版本均未成功&#xff0c;原因不明☹️ 1. 准备工作 ⏬ 下载地址&#xff1a;https://downloads.mysql.com/archives/community/ 2. 清理历史环境 不用管…

C++多继承

可以用多个基类来派生一个类。 格式为&#xff1a; class 类名:类名1,…, 类名n { private: … &#xff1b; //私有成员说明; public: … &#xff1b; //公有成员说明; protected: … &#xff1b; //保护的成员说明; }; class D: public A, protected B, private C { …//派…

某地老旧房屋自动化监测项目

1. 项目简介 自从上个世纪90年代以来&#xff0c;我国经济发展迅猛&#xff0c;在此期间大量建筑平地而起&#xff0c;并且多为砖混结构的住房&#xff0c;使用寿命通常约为30-50年&#xff0c;钢筋混凝土结构&#xff0c;钢结构等高层建筑&#xff0c;这些建筑在一般情况下的…

产品经理的大语言模型课 04 -模型应用的云、边、端模式对比

目录 算力部署方式的影响因素数据量计算难度前期投入数据隐私应用规模与泛化能力 云、边、端部署的特点和对比典型场景举例社区人脸门禁后厨老鼠识别 未来展望 算力部署方式的影响因素 最近和人工智能从业者进行了非常广泛的沟通&#xff0c;尝试对模型应用的云、边、端模式进…

基于Python设计的TEQC数据质量可视化分析软件

标题:基于Python设计的TEQC数据质量可视化分析软件 内容:1.摘要 本文旨在设计一款基于Python的TEQC数据质量可视化分析软件。随着全球导航卫星系统&#xff08;GNSS&#xff09;的广泛应用&#xff0c;数据质量的评估变得至关重要。TEQC&#xff08;TransEditQualityCheck&…

Flinksql--订单宽表

参考&#xff1a; https://chbxw.blog.csdn.net/article/details/115078261 (datastream 实现) 一、ODS 模拟订单表及订单明细表 CREATE TABLE orders (order_id STRING,user_id STRING,order_time TIMESTAMP(3),-- 定义事件时间及 Watermark&#xff08;允许5秒乱序&#x…

粒子滤波介绍

目录 粒子滤波的主要流程可以分为以下 5 个步骤&#xff1a; 粒子滤波&#xff08;PF&#xff09; vs. ESKF&#xff08;误差状态卡尔曼滤波&#xff09; 粒子滤波的主要流程可以分为以下 5 个步骤&#xff1a; 初始化&#xff08;Initialization&#xff09; 生成 N 个粒子&…

一场国际安全厂商的交流会议简记

今天参与了一场国际安全厂商A公司组织的交流会议 与会有国际TOP企业跨境企业 还有国内一些头部商业公司。 A公司很有意思介绍了自己是怎么做安全运营中心SOC的。 介绍了很多内容&#xff0c;包括他们自己的员工量/设备量/事件量/SOC中心人员量&#xff0c;其中人员量只有个位数…

Java面试黄金宝典30

1. 请详细列举 30 条常用 SQL 优化方法 定义 SQL 优化是指通过对 SQL 语句、数据库表结构、索引等进行调整和改进&#xff0c;以提高 SQL 查询的执行效率&#xff0c;减少系统资源消耗&#xff0c;提升数据库整体性能的一系列操作。 要点 从索引运用、查询语句结构优化、数据…

花洒洗澡完毕并关闭后过段时间会突然滴水的原因探究

洗澡完毕后的残留水 在洗澡的过程中&#xff0c;我们通常会使用到大量的水。这些水会通过花洒管子到达花洒顶喷流出。由于大顶喷花洒的喷头较大&#xff0c;关闭后里面的存水会更多。 气压失衡后的滴水 当花洒关闭后&#xff0c;内部的水管和花洒头中仍存有一定量的水。由于…

QSettings用法实战(相机配置文件的写入和读取)

很多情况&#xff0c;在做项目开发的时候&#xff0c;将参数独立出来是比较好的方法 例如&#xff1a;相机的曝光次数、曝光时长等参数&#xff0c;独立成ini文件&#xff0c;用户可以在外面修改即可生效&#xff0c;无需在动代码重新编译等工作 QSettings便可以实现该功能 内…

运维培训班之最佳选择(The best Choice for Operation and Maintenance Training Courses)

运维培训班之最佳选择 从面试官的角度聊聊培训班对运维的帮助&#xff0c;同时给培训班出身的运维一些建议~ 谈到运维&#xff08;尤其是零基础非科班转行的运维&#xff09;找工作&#xff0c;培训班是个不可回避的讨论热点。虽然本人也做过兼职运维培训老师&#xff0c;多少…

网络安全与防护策略

随着信息技术的飞速发展&#xff0c;互联网已成为现代社会不可或缺的一部分。从日常生活到企业运营&#xff0c;几乎所有活动都离不开网络。然而&#xff0c;网络的开放性和广泛性也使得网络安全问题愈发严峻。无论是个人数据泄露&#xff0c;还是大规模的网络攻击&#xff0c;…

LLM 分词器Tokenizer 如何从 0 到 1 训练出来

写在前面 大型语言模型(LLM)处理的是人类的自然语言,但计算机本质上只能理解数字。Tokenizer(分词器) 就是架在自然语言和计算机数字表示之间的一座至关重要的桥梁。它负责将我们输入的文本字符串分解成模型能够理解的最小单元——Token,并将这些 Token 转换成对应的数字…

【ArcGIS微课1000例】0142:如何从谷歌地球保存高清影像图片

文章目录 一、选取影像区域1. 搜索地图区域2. 导入矢量范围二、添加输出图层三、保存高清影像1. 地图选项2. 输出分辨率3. 保存图像四、注意事项一、选取影像区域 首先需要选取影像区域,可通过以下方式快速定位。 1. 搜索地图区域 在搜索框内输入关键词,例如青海湖,点击【…

Unity注册表修改分辨率:探索幕后设置与手动调控

Unity注册表修改分辨率&#xff1a;探索幕后设置与手动调控 在Unity开发中&#xff0c;调整分辨率和显示模式是开发过程中常见的需求&#xff0c;尤其是当我们打包并运行应用时&#xff0c;可能会遇到显示模式不符合预期的情况。Unity在首次运行时会自动保存这些设置&#xff…

外部流输入的 Layer

在 Android 的 SurfaceFlinger 体系中&#xff0c;外部流输入的 Layer 通常通过 Sideband Stream 或 BufferQueue 机制传递给 SurfaceFlinger&#xff0c;然后由 HWC&#xff08;Hardware Composer&#xff09;或 OpenGL ES 进行合成。 1. 什么是外部流输入的 Layer&#xff1f…

31-体测管理系统

介绍 技术&#xff1a; 基于 B/S 架构 SpringBootMySQLvueelementui 环境&#xff1a; Idea mysql maven jdk1.8 node 用户端功能 1.系统首页展示轮播图及公告信息 2.测试项目:展示可以参加测试的项目列表 3.公告信息:公告信息列表及详情 可进行点赞和收藏 4.在线留言 5.个人…

NVR接入录像回放平台EasyCVR视频系统守护舌尖上的安全,打造“明厨亮灶”云监管平台

一、方案背景 近年来&#xff0c;餐饮行业食品安全和卫生等问题频发&#xff0c;比如后厨卫生脏乱差等&#xff0c;持续引发关注&#xff0c;这些事情导致连锁反应&#xff0c;使其收益遭受损失。同时&#xff0c;给消费者造成了心理和生理上的伤害。 加强餐饮行业的监管成为…