Qt中MVD模式的具体使用
作者:寻找华年的锦瑟
本文主要介绍了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的一部分。
- QListWidget、QTableWidget、QTreeWidget:这些是方便类,内部已经集成了模型,适用于简单应用。但它们不符合严格的MVC模式,因为模型和视图是捆绑在一起的。
四、delegate
常用的委托方式:
- 使用内置委托:QT提供了一些内置的委托类,如
QStyledItemDelegate和QItemDelegate。通常推荐使用QStyledItemDelegate,因为它使用当前样式来绘制项目。 内置委托: - QT的内置委托可以处理大多数常见的数据类型(如字符串、数字、日期等)的显示和编辑。例如,当你在一个模型/视图结构中编辑一个布尔值时,内置委托会提供一个复选框;编辑数字时,会提供一个数字输入框等。
- 自定义委托:通过继承
QStyledItemDelegate或QItemDelegate,并重写其虚函数来实现自定义的显示和编辑行为。 - 自定义委托:自定义委托通常需要重写以下一个或多个函数:
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模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
