Qt模型视图代理之MVD(模型-视图-代理)概念的简单介绍

本文介绍了Qt中的图形视图、模型-视图-代理(MVD)模式,包括模型的职责、视图的作用以及代理在数据编辑中的角色。重点讲解了模型索引在数据定位和展示中的关键作用,以及如何通过MVD模式实现数据独立管理和高效交互。
摘要由CSDN通过智能技术生成

往期回顾

Qt绘图与图形视图之Graphics View坐标系的简单介绍-CSDN博客

Qt绘图与图形视图之基本图元绘制的简单介绍-CSDN博客

Qt绘图与图形视图之自定义图元实现拖拽、拉伸、旋转功能-CSDN博客

 Qt模型视图代理之MVD(模型-视图-代理)概念的简单介绍

一、基本概念

Qt模型视图代理,也可以称为MVD模式,

模型(model)、视图(view)、代理(delegate),主要用来显示编辑数据。

记住关键词:显示、编辑。

Qt模型-视图-代理是Qt框架中用于实现数据展示和交互的重要机制。

二、什么是模型-视图-代理

1、模型(model)

模型(Model)是视图与原始数据之间的接口,原始数据可以是数据库的一个数据表、内存中的一个StringList,磁盘文件结构等。

模型是数据的抽象接口,用于存储、检索和操作数据。

模型负责管理数据的结构和内容,提供数据的读取、写入和修改功能。
模型与视图和代理之间起到了桥梁的作用,使得数据能够以一种通用的方式被视图显示和修改。

QsqlTableModel表示数据库中数据表的模型

QAbstractltemModel所有模型的祖宗类,其它model类 都派生于它。

2、视图(View)

视图(View)是显示和编辑数据的界面组件。主要的视图组件有QListView、QTreeView和QTableView,QListWidget、QTreeWidget和QTableWidget是视图类的简化版,它们不使用数据模型,而是将数据直接存储在组件的每个项里。

视图是用来展示模型中数据的UI组件
视图可以显示模型中的数据,支持数据的排序、过滤、选择等操作。
视图负责将模型中的数据以可视化的方式呈现给用户,并允许用户与数据进行交互。

就数据操作而言,单列的列表数据,适合一维数据操作,显示表格操作,适合二维表格数据操作 

3、代理(Delegate)

代理(Delegate)代理为视图组件提供辑数据编辑器,如在表格组件中,编辑一个单元格的数据时,缺省(默认)是使用一个QLineEdit编辑框。代理负责从数据模型获取相应的数据,然后显示在编辑器里,修改数据后,又将其保存到数据模型中。

代理是模型和视图之间的中间层,用于对模型数据进行过滤、排序、修改等操作,以满足视图的需求。

代理可以对模型中的数据进行转换和处理,使得视图能够以不同的方式展示数据,同时保持模型数据的不变。

常见的代理包括QSortFilterProxyModel、QIdentityProxyModel等,用于实现数据的排序、过滤等功能。

QAbstractltemDelegate是所有代理类的抽象基类。

QStyledltemDelegate是视图组件使用的缺省(默认)的代理类。

4、作用

通过模型-视图-代理机制,Qt框架实现了数据与UI的分离,使得数据可以独立于UI进行管理和操作,同时提供了灵活的方式来展示和交互数据。这种设计模式使得Qt应用程序更易于维护和扩展,提高了代码的可读性和可重用性。

三、模型索引

模型索引(Model、Index)是在Qt中用于唯一标识模型中数据项的类。

模型索引包含了指向特定数据项的行号和列号等信息,以便视图可以准确地定位和访问模型中的数据。模型索引在模型-视图架构中起着非常重要的作用,因为它们允许视图根据索引从模型中检索数据,并在视图中正确地显示数据。

在使用代理模型时,代理模型通常会使用模型索引来访问原始模型中的数据,并对数据进行转换、过滤或其他操作,然后将处理后的数据提供给视图进行显示。通过模型索引,代理模型可以准确地定位原始模型中的数据项,并对其进行处理。


以上就是Qt里MVD(模型-视图-代理)概念的简单介绍。

都看到这里了,点个赞再走呗朋友~

加油吧,预祝大家变得更强!

  • 19
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单QT C++ MVD(Model-View-Delegate)例子: Model.h: ```cpp #ifndef MODEL_H #define MODEL_H #include <QAbstractListModel> #include <QStringList> class Model : public QAbstractListModel { Q_OBJECT public: explicit Model(QObject *parent = nullptr); enum { NameRole = Qt::UserRole, AgeRole }; // 声明 QAbstractListModel 纯虚函数 int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; // 自定义函数 bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; Qt::ItemFlags flags(const QModelIndex &index) const override; void addPerson(const QString &name, int age); private: struct Person { QString name; int age; }; QList<Person> m_persons; }; #endif // MODEL_H ``` Model.cpp: ```cpp #include "Model.h" Model::Model(QObject *parent) : QAbstractListModel(parent) { } int Model::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_persons.count(); } QVariant Model::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); const auto &person = m_persons.at(index.row()); switch (role) { case Qt::DisplayRole: case NameRole: return person.name; case AgeRole: return person.age; default: break; } return QVariant(); } bool Model::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid() || role != Qt::EditRole) return false; auto &person = m_persons[index.row()]; switch (index.column()) { case 0: person.name = value.toString(); break; case 1: person.age = value.toInt(); break; default: return false; } emit dataChanged(index, index, {role}); return true; } Qt::ItemFlags Model::flags(const QModelIndex &index) const { auto flags = QAbstractListModel::flags(index); if (index.isValid()) flags |= Qt::ItemIsEditable; return flags; } void Model::addPerson(const QString &name, int age) { beginInsertRows(QModelIndex(), rowCount(), rowCount()); m_persons.append({name, age}); endInsertRows(); } ``` Delegate.h: ```cpp #ifndef DELEGATE_H #define DELEGATE_H #include <QStyledItemDelegate> class Delegate : public QStyledItemDelegate { Q_OBJECT public: explicit Delegate(QObject *parent = nullptr); // 声明 QStyledItemDelegate 纯虚函数 QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void setEditorData(QWidget *editor, const QModelIndex &index) const override; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; }; #endif // DELEGATE_H ``` Delegate.cpp: ```cpp #include "Delegate.h" #include <QLineEdit> Delegate::Delegate(QObject *parent) : QStyledItemDelegate(parent) { } QWidget *Delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const { auto editor = new QLineEdit(parent); return editor; } void Delegate::setEditorData(QWidget *editor, const QModelIndex &index) const { const auto &text = index.model()->data(index, Qt::EditRole).toString(); auto lineEdit = static_cast<QLineEdit *>(editor); lineEdit->setText(text); } void Delegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { auto lineEdit = static_cast<QLineEdit *>(editor); const auto &text = lineEdit->text(); model->setData(index, text, Qt::EditRole); } void Delegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const { editor->setGeometry(option.rect); } ``` MainWindow.h: ```cpp #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> class Model; namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void on_addButton_clicked(); private: Ui::MainWindow *ui; Model *m_model; }; #endif // MAINWINDOW_H ``` MainWindow.cpp: ```cpp #include "MainWindow.h" #include "ui_MainWindow.h" #include "Model.h" #include "Delegate.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), m_model(new Model(this)) { ui->setupUi(this); ui->tableView->setModel(m_model); ui->tableView->setItemDelegate(new Delegate(this)); ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection); ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_addButton_clicked() { const auto &name = ui->nameEdit->text(); const auto age = ui->ageSpinBox->value(); m_model->addPerson(name, age); } ``` 使用 QT Designer 创建一个 MainWindow.ui 界面,包含一个 QTableView 和两个 QLineEdit,一个 QSpinBox 和一个 QPushButton。 MainWindow.ui: ``` <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>640</width> <height>480</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"> <widget class="QTableView" name="tableView"> <geometry> <rect> <x>20</x> <y>20</y> <width>600</width> <height>300</height> </rect> </geometry> </widget> <widget class="QLineEdit" name="nameEdit"> <geometry> <rect> <x>20</x> <y>350</y> <width>200</width> <height>20</height> </rect> </geometry> </widget> <widget class="QSpinBox" name="ageSpinBox"> <geometry> <rect> <x>240</x> <y>350</y> <width>80</width> <height>20</height> </rect> </geometry> </widget> <widget class="QPushButton" name="addButton"> <geometry> <rect> <x>340</x> <y>350</y> <width>80</width> <height>20</height> </rect> </geometry> <property name="text"> <string>Add</string> </property> </widget> </widget> </widget> <resources/> <connections/> </ui> ``` 最终效果如下: ![QT C++ MVD 例子](https://img-blog.csdnimg.cn/2021070509285015.png)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值