Qt中MVD模式的具体使用

 更新时间:2026年03月26日 09:31:45   作者:寻找华年的锦瑟  
本文主要介绍了Qt中MVD模式的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、前言

  MVD 模式的核心价值:关注点分离,让数据管理、显示逻辑和用户交互各自独立,从而创建出更可维护、可扩展的应用程序。

Model: 完全不知道数据会如何显示,只负责存储和管理数据。

View :视图作为桥梁,从 Model 获取数据、将数据传递给 Delegate 进行渲染、处理用户交互事件

Delegate :委托完全控制每个项目的外观,包括颜色、布局、边框等。

好处:

修改方便:

  • 可以轻松更换不同的 Model 来改变数据源
  • 可以轻松更换不同的 View 来改变交互方式
  • 可以轻松更换不同的 Delegate 来改变外观

 松耦合设计

  • 修改数据不影响显示逻辑
  • 修改显示样式不影响数据
  • 各部分可以独立开发和测试

二、Model

 基础模型类型:

QStringListModel - 字符串列表模型

#include <QStringListModel>

QStringListModel *model = new QStringListModel;
model->setStringList({"苹果", "香蕉", "橙子"});

QStandardItemModel - 标准项目模型

#include <QStandardItemModel>

QStandardItemModel *model = new QStandardItemModel;
model->appendRow(new QStandardItem("项目1"));

QFileSystemModel - 文件系统模型

#include <QFileSystemModel>

QFileSystemModel *model = new QFileSystemModel;
model->setRootPath(QDir::homePath());

三、View

  • QListView:将数据项显示为列表。
  • QTableView:将数据项显示在表格中。
  • QTreeView:将数据项显示在层次结构的树中。
  • QColumnView:使用多个列显示数据项,每个列代表一个层次级别。
  • QHeaderView:用于显示表格或列表的标题行或标题列,通常不单独使用,而是作为QTableView和QTreeView的一部分。
  • QListWidgetQTableWidgetQTreeWidget:这些是方便类,内部已经集成了模型,适用于简单应用。但它们不符合严格的MVC模式,因为模型和视图是捆绑在一起的。

四、delegate

常用的委托方式:

  • 使用内置委托:QT提供了一些内置的委托类,如QStyledItemDelegateQItemDelegate。通常推荐使用QStyledItemDelegate,因为它使用当前样式来绘制项目。 内置委托:
  • QT的内置委托可以处理大多数常见的数据类型(如字符串、数字、日期等)的显示和编辑。例如,当你在一个模型/视图结构中编辑一个布尔值时,内置委托会提供一个复选框;编辑数字时,会提供一个数字输入框等。
  • 自定义委托:通过继承QStyledItemDelegateQItemDelegate,并重写其虚函数来实现自定义的显示和编辑行为。
  •  自定义委托:自定义委托通常需要重写以下一个或多个函数:
    • paint(): 用于自定义项目的显示。
    • sizeHint(): 返回项目的大小。
    • createEditor(): 返回一个用于编辑项目的部件(如QLineEdit、QComboBox等)。
    • setEditorData(): 将模型中的数据设置到编辑器。
    • setModelData(): 将编辑器中的数据保存到模型。
    • updateEditorGeometry(): 设置编辑器在视图中的位置和大小。

五、案例

.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QListView>
#include <QStringListModel>
#include <QStyledItemDelegate>
#include <QPainter>
#include <QVBoxLayout>
#include <QWidget>
// 前向声明
class QListView;
class QStringListModel;
class SimpleDelegate;
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
private:
    void setupUI();
    void setupModel();
    QListView *listView;
    QStringListModel *model;
    SimpleDelegate *delegate;
};
#endif // MAINWINDOW_H

.cpp

#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QListView>
#include <QStringListModel>
#include <QStyledItemDelegate>
#include <QPainter>
#include <QVBoxLayout>
#include <QWidget>
class SimpleDelegate : public QStyledItemDelegate
{
public:
    explicit SimpleDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        // 绘制背景
        if (option.state & QStyle::State_Selected) {
            painter->fillRect(option.rect, QColor(173, 216, 230)); // 浅蓝色选中背景
        } else {
            painter->fillRect(option.rect, Qt::white); // 白色默认背景
        }
        // 绘制文本
        QString text = index.data(Qt::DisplayRole).toString();
        painter->setPen(Qt::black);
        painter->drawText(option.rect, Qt::AlignCenter, text);
        // 绘制边框
        painter->setPen(Qt::lightGray);
        painter->drawRect(option.rect.adjusted(0, 0, -1, -1));
    }
    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        // 设置项目大小
        QSize size = QStyledItemDelegate::sizeHint(option, index);
        size.setHeight(40); // 固定高度
        return size;
    }
};
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , listView(new QListView(this))
    , model(new QStringListModel(this))
    , delegate(new SimpleDelegate(this))
{
     ui->setupUi(this);
    setupUI();
    setupModel();
    setWindowTitle("QT6 MVD 简单示例");
    resize(300, 300);
}
void MainWindow::setupUI()
{
    // 创建中央部件
    QWidget *centralWidget = new QWidget(this);
    setCentralWidget(centralWidget);
    // 设置列表视图属性
    listView->setModel(model);
    listView->setItemDelegate(delegate);
    listView->setAlternatingRowColors(true); // 交替行颜色
    // 创建布局
    QVBoxLayout *layout = new QVBoxLayout(centralWidget);
    layout->addWidget(listView);
}
void MainWindow::setupModel()
{
    // 创建示例数据
    QStringList data;
    data << "任务1: 学习 QT6"
         << "任务2: 理解 MVD 模式"
         << "任务3: 编写示例代码"
         << "任务4: 测试应用程序"
         << "任务5: 优化界面效果";
    // 设置模型数据
    model->setStringList(data);
}
MainWindow::~MainWindow()
{
    delete ui;
}

结果:

功能演示:

我可一只修改delegate中的 painter->fillRect(option.rect, Qt::white); // 白色默认背景将背景变为red;

到此这篇关于Qt中MVD模式的具体使用的文章就介绍到这了,更多相关Qt MVD模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言实现wave波形

    C语言实现wave波形

    本文详细讲解了C语言实现wave波形的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2021-12-12
  • 关于C语言 文件读写 feof 函数

    关于C语言 文件读写 feof 函数

    这篇文章主要给大家分享的是关于C语言文件读写 feof 函数 ,feof 是 C 语言标准库函数,其功能是检测文件结束符,如果文件结束,则返回非 0 值,否则返回 0,感兴趣的小伙伴请跟小编一起来看看下面文章的内容吧
    2021-10-10
  • MFC实现漂亮界面之美化按钮

    MFC实现漂亮界面之美化按钮

    这篇文章主要为大家详细介绍了MFC实现漂亮界面之美化按钮,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-02-02
  • Qt使用QPainter实现自定义圆形进度条

    Qt使用QPainter实现自定义圆形进度条

    这篇文章主要介绍了Qt如何使用QPainter实现自定义圆形进度条功能,文中的示例代码讲解详细,对我们学习Qt有一定的帮助,需要的可以参考一下
    2022-06-06
  • C++动态内存分配超详细讲解

    C++动态内存分配超详细讲解

    给数组分配多大的空间?你是否和初学C时的我一样,有过这样的疑问。这一期就来聊一聊动态内存的分配,读完这篇文章,你可能对内存的分配有一个更好的理解
    2022-08-08
  • 新手向超详细的C语言实现动态顺序表

    新手向超详细的C语言实现动态顺序表

    本文主要介绍了C语言实现动态顺序表,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • 利用Matlab实现阴影柱状图的绘制

    利用Matlab实现阴影柱状图的绘制

    阴影柱状图绘制的代码MATHWORKS上也有,不过是生成图片后,识别图像上不同颜色块并直接修改像素生成阴影线。这样的生成方式不可逆且自由度较低,所以本文为大家带来的是一个直接画线条填充的硬画版本,希望有所帮助
    2022-09-09
  • C++详细讲解模拟实现位图和布隆过滤器的方法

    C++详细讲解模拟实现位图和布隆过滤器的方法

    位图(bitset)是一种常用的数据结构,常用在给一个很大范围的数,判断其中的一个数是不是在其中。在索引、数据压缩方面有很大的应用。布隆过滤器是由布隆提出的,它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中
    2022-06-06
  • C++实现LeetCode(137.单独的数字之二)

    C++实现LeetCode(137.单独的数字之二)

    这篇文章主要介绍了C++实现LeetCode(137.单独的数字之二),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C语言的模板与泛型编程你了解吗

    C语言的模板与泛型编程你了解吗

    这篇文章主要为大家详细介绍了C语言的模板与泛型编程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03

最新评论