Qt之MVC架构MVD

news2025/3/22 6:41:47

什么是MVC架构:

MVC模式(Model–view–controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

MVC模式最早由Trygve Reenskaug在1978年提出[1],是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件架构。MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。除此之外,此模式透过对复杂度的简化,使程序结构更加直观。软件系统透过对自身基本部分分离的同时也赋予了各个基本部分应有的功能。专业人员可以依据自身的专长分组:

模型(Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。

视图(View) - 界面设计人员进行图形界面设计。

控制器(Controller)- 负责转发请求,对请求进行处理。

Qt的MVD架构又是什么?

模型(Model) - 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。

视图(View) - 界面设计人员进行图形界面设计。

代理(Delegate)- 负责转发请求,对请求进行处理

UI样式实现:

其实你就只要去实现下面的代码,你就能完全使用MVD架构,随心所欲

class TableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    enum Columns { Element = 0, Value, Count = Value + 1 };
    explicit TableModel(QObject *parent = nullptr);
    
    Qt::ItemFlags flags(const QModelIndex &index) const;
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;


    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole);

    void addElement(const QString &element, int value);

private:

};
class TableDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit TableDelegate(QObject *parent = nullptr);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};



//--------------------cpp---------------------
#include "tablemodel.h"

TableModel::TableModel(QObject *parent) : QAbstractTableModel(parent)
{
}

Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
{
    return QAbstractTableModel::flags(index);
}

int TableModel::rowCount(const QModelIndex &parent) const
{
    return 2;
}

int TableModel::columnCount(const QModelIndex &parent) const
{
    return Count;
}

QVariant TableModel::data(const QModelIndex &index, int role) const
{
    return QVariant();
}

QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    return QAbstractTableModel::headerData(section, orientation, role);
}

bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid() || index.row() < 0 || index.row() >= mElements.count())
    {
        return false;
    }
    return false;
}
void TableModel::addElement(const QString &element, int value)
{
}


TableDelegate::TableDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
}


QWidget *TableDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                                     const QModelIndex &index) const
{
    return QStyledItemDelegate::createEditor(parent, option, index);
}


void TableDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QStyledItemDelegate::setEditorData(editor, index);
}


void TableDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QStyledItemDelegate::setModelData(editor, model, index);
}


void TableDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyledItemDelegate::paint(painter, option, index);
}


void TableDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                                         const QModelIndex &index) const
{
    Q_UNUSED(index)
    editor->setGeometry(option.rect);
}

Model

class QAbstractItemModel {
    virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const = 0;
    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const = 0;
    virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) = 0;
    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const = 0;
    virtual int columnCount(const QModelIndex &parent = QModelIndex()) const = 0;
    virtual Qt::ItemFlags flags(const QModelIndex &index) const = 0;
};

实现上面的代码,你就能使用MVD架构,理解Qt的框架,

View 与 Model 的绑定流程

当调用 view->setModel(model)时:
  1. 存储指针:View 内部保存QAbstractItemModel*类型的指针指向用户的 Model 对象
  2. 信号连接:View 自动连接 Model 的信号(如 dataChanged())到自身的槽(如 update()),实现数据变化时的视图更新
  3. 数据请求:当视图需要渲染时,会通过 Model 指针调用虚函数(如data()rowCount())
// 伪代码:QAbstractItemView 的渲染流程
void QAbstractItemView::paintEvent() {
    for (int row = 0; row < model->rowCount(); ++row) { // 多态调用 model->rowCount()
        QVariant data = model->data(index(row));        // 多态调用 model->data()
        delegate->paint(painter, data);                 // 多态调用 delegate->paint()
    }
}

Delegate 的动态调用机制

当设置 view->setItemDelegate(delegate)  后:
  1. 渲染阶段:View 在绘制每个数据项时,调用delegate->paint(painter, option, index)
  2. 编辑阶段:当用户双击单元格时,调用delegate->createEditor()创建编辑器
  3. 数据回写:编辑器关闭时,调用delegate->setModelData()将数据写回 Model
// 伪代码:委托的编辑器创建过程
void QAbstractItemView::edit(const QModelIndex &index) {
    QWidget* editor = delegate->createEditor(parent, option, index); // 多态调用
    connect(editor, &QWidget::destroyed, [this, index]() {
        delegate->setModelData(editor, model, index); // 多态调用
    });
}

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

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

相关文章

深度解析学术论文成果评估(Artifact Evaluation):从历史到现状

深度解析学术论文成果评估(Artifact Evaluation)&#xff1a;从历史到现状 引言 在计算机科学和工程领域的学术研究中&#xff0c;可重复性和可验证性越来越受到重视。随着实验性研究的复杂性不断增加&#xff0c;确保研究成果可以被其他研究者验证和构建变得尤为重要。这一需…

二分查找上下界问题的思考

背景 最近在做力扣hot100中的二分查找题目时&#xff0c;发现很多题目都用到了二分查找的变种问题&#xff0c;即二分查找上下界问题&#xff0c;例如以下题目&#xff1a; 35. 搜索插入位置 74. 搜索二维矩阵 34. 在排序数组中查找元素的第一个和最后一个位置 它们不同于查找…

关于FastAPI框架的面试题及答案解析

FastAPl是一个现代、快速(高性能)的Web框架,用于构建API,基于Python3.7+的类型提示功能。它由Python开发者SebastianRamirez创建,并且使用了Starlette作为其核心组件以及Pydantic进行数据验证。 文章目录 基础篇1. FastAPI的核心优势是什么?2. 如何定义一个GET请求路由?…

HashMap添加元素的流程图

文章目录 JDK7 vs JDK8 的 HashMap 结构变化Java8 中哈希表的红黑树优化机制HashMap 添加元素的完整流程解析1. 计算 key 的哈希值并确定索引2. 检查该索引位置是否已有元素3. 处理哈希冲突4. 判断当前存储结构&#xff08;链表还是红黑树&#xff09;5. 判断链表长度是否超过 …

面向医药仓储场景下的药品分拣控制策略方法 研究(大纲)

面向医药仓储场景下的药品分拣控制策略方法研究 基于多机器人协同与智能调度的分拣系统设计 第一章 绪论 1.1 研究背景与意义 医药仓储自动化需求&#xff1a; 人工分拣效率低、出错率高&#xff08;如药品批次混淆、过期风险&#xff09;温控药品&#xff08;如疫苗、生物制…

AI大模型介绍

大模型介绍 大模型是指具有大规模参数和复杂计算结构的机器学习模型&#xff0c;通常由深度神经网络构建而成&#xff0c;拥有数十亿甚至数千亿个参数 开发大模型不是从0开始&#xff0c;是建立在已有的大模型基座模型上做开发&#xff0c;构建企业知识库&#xff08;向量数据库…

OpenPCDet详细部署与复现

OpenPCDet简介 OpenPCDet是一个用于3D目标检测的开源工具箱&#xff0c;它提供了多种数据集的加载器&#xff0c;支持多种模型&#xff0c;并且易于扩展。 本人使用硬件与环境 Linux操作系统&#xff08;Ubuntu20.04&#xff09; Python环境&#xff08;Anaconda下独立创建&…

同旺科技USB to I2C 适配器 ---- 指令之间延时功能

所需设备&#xff1a; 内附链接 1、同旺科技USB to I2C 适配器 1、指令之间需要延时发送怎么办&#xff1f;循环过程需要延时怎么办&#xff1f;如何定时发送&#xff1f;现在这些都可以轻松解决&#xff1b; 2、只要在 “发送数据” 栏的Delay单元格里面输入相应的延迟时间就…

网络华为HCIA+HCIP NFV

目录 NFV关键技术&#xff1a;虚拟化 NFV关键技术&#xff1a;云化 NFV架构 NFV标准架构 ​编辑 NFV架构功能模块 NFV架构接口 NFV关键技术&#xff1a;虚拟化 在NFV的道路上&#xff0c;虚拟化是基础&#xff0c;云化是关键。传统电信网络中&#xff0c;各个网元都是…

MySQL0基础学习记录-下载与安装

下载 下载地址&#xff1a; &#xff08;Windows&#xff09;https://dev.mysql.com/downloads/file/?id536787 安装 直接点next&#xff0c;出现&#xff1a; 点execute 然后一直next到这页&#xff1a; next 然后需要给root设置一个密码&#xff1a; 在next。。很多页…

集成学习(下):Stacking集成方法

一、Stacking的元学习革命 1.1 概念 Stacking&#xff08;堆叠法&#xff09; 是一种集成学习技术&#xff0c;通过组合多个基学习器&#xff08;base learner&#xff09;的预测结果&#xff0c;并利用一个元模型&#xff08;meta-model&#xff09;进行二次训练&#xff0c…

背包问题——动态规划的经典问题包括01背包问题和完全背包问题

01背包问题&#xff1a;给你多个物品每个物品只能选一次&#xff0c;要你在不超过背包容积&#xff08;或者恰好等于&#xff09;的情况下选择装价值最大的组合。如果没有动态规划的基础其实是很难理解这个问题的&#xff0c;所以看这篇文章之前先去学习一下动态规划的基本思想…

MyBatis 面试专题

MyBatis 面试专题 基础概念MyBatis中的工作原理MyBatis 与 Hibernate 的区别&#xff1f;#{} 和 ${} 的区别&#xff1f;MyBatis 的核心组件有哪些&#xff1f; 映射与配置如何传递多个参数&#xff1f;ResultMap 的作用是什么&#xff1f;动态 SQL 常用标签有哪些&#xff1f;…

Animation - AI Controller控制SKM_Manny的一些问题

一些学习笔记归档&#xff1b; 在UE5中&#xff0c;使用新的小白人骨骼&#xff1a;SKM_Manny&#xff0c;会跟UE4中的小白人有一些差别&#xff1b; 比如在用AI Controller控制使用该骨骼&#xff08;配置默认的ABP_Manny Animation BP&#xff09;角色的时候&#xff0c;需要…

安科瑞新能源防逆流解决方案:守护电网安全,赋能绿色能源利用

随着光伏、储能等新能源在用户侧的快速普及&#xff0c;如何避免电力逆流对电网造成冲击&#xff0c;成为行业关注的焦点。安科瑞凭借技术实力与丰富的产品矩阵&#xff0c;推出多场景新能源防逆流解决方案&#xff0c;以智能化手段助力用户实现安全、经济的能源管理&#xff0…

【一起学Rust | Tauri2.0框架】基于 Rust 与 Tauri 2.0 框架实现全局状态管理

前言 在现代应用程序开发中&#xff0c;状态管理是构建复杂且可维护应用的关键。随着应用程序规模的增长&#xff0c;组件之间共享和同步状态变得越来越具有挑战性。如果处理不当&#xff0c;状态管理可能会导致代码混乱、难以调试&#xff0c;并最终影响应用程序的性能和可扩…

扩散模型算法实战——三维重建的应用

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​ ​​​​​​ ​ ​ 1. 引言 三维重建是计算机视觉和图形学中的一个重要研究方向&#xff0c;旨在从二维图像或其他传感器数据中恢复…

社群经济4.0时代:开源链动模式与AI技术驱动的电商生态重构

摘要&#xff1a;在Web3.0技术浪潮与私域流量红利的双重驱动下&#xff0c;电商行业正经历从"流量收割"到"用户深耕"的范式转变。本文基于社群经济理论框架&#xff0c;结合"开源链动21模式"、AI智能名片、S2B2C商城小程序源码等创新工具&#x…

【Linux系统】进程等待:告别僵尸进程深入理解Linux进程同步的核心密码

Linux系列 文章目录 Linux系列前言一、进程等待的核心目的二、进程等待的实现方式2.1 wait()函数2.2 waitpid&#xff08;&#xff09;函数 总结 前言 在Linux系统中&#xff0c;进程等待&#xff08;Process Waiting&#xff09;是多进程编程中的核心机制&#xff0c;指父进程…

六十天前端强化训练之第二十五天之组件生命周期大师级详解(Vue3 Composition API 版)

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 一、生命周期核心知识 1.1 生命周期全景图 1.2 生命周期钩子详解 1.2.1 初始化阶段 1.2.2 挂载阶段 1.2.3 更新阶段 1.2.4 卸载阶段 1.3 生命周期执行顺序 1.4 父子组…