当前位置: 首页 > news >正文

Qt之MVC架构MVD

什么是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); // 多态调用
    });
}

相关文章:

  • cmake教程
  • JAVA URL和URI差异对比
  • C语言入门知识(上)
  • 搭建React简单项目
  • lua垃圾回收
  • javaAPI文档中文版(在线版)
  • 绿盟面试题
  • centos家用笔记
  • 智能汽车图像及视频处理方案,支持视频智能拍摄能力
  • ModuleNotFoundError: No module named ‘flask‘ 错误
  • Cursor/windsurf+MCP+Blender自动建模还有多远
  • JimuReport与deepseek结合,颠覆现有BI模式
  • ASFF:Learning Spatial Fusion for Single-Shot Object Detection
  • 蓝桥杯 积木画
  • llama源码学习·model.py[3]ROPE旋转位置编码(4)ROPE的应用
  • Python八字排盘系统实现分析
  • flutter报错:Could not find com.meituan.android.walle:plugin
  • centos7.9 脚本一键升级到openssl-3.4.0,openssh-9.9p1
  • JSON 解析中需要清理的危险字符
  • 解析Collections工具类主要功能
  • 浙江广厦:诚挚道歉,涉事责任人交公安机关
  • 持续降雨存在落石风险,贵州黄果树景区水帘洞将封闭至6月初
  • 茅台总经理到访五粮液:面对白酒行业周期性调整,需要团结一心的合力
  • 香港特区政府强烈谴责美参议员恐吓国安人员
  • 长三角体育节回归“上海时间”,首次发布赛事旅游推荐线路
  • 恒生银行回应裁员传闻:受影响的员工数目占银行核心业务员工总数约1%