16、Model_View_Delegate

发布时间 2023-12-12 16:36:58作者: 秃头的C#

  QT当中model-view-delegate(模型-视图-代理),此结构实现数据和界面的分离。Qt的模型-视图结构分为三部分:模型(model)-视图(view)-代理(Delegate)。其中模型与数据源通信;并为其它部件提供接口;视图从模型中引用数据条目的模型索引(ModelIndex)。在视图当中,代理负责绘制数据条目,比如编辑条目,代理和模型进行直接通信。

关系

模型、视图、代理是MVC模式中的三个核心组件,各自承担不同的职责。

  • 模型(Model):负责存储数据和对数据进行处理,提供访问和修改数据的接口。模型通常是应用程序最底层的部分,与具体业务逻辑有关。
  • 视图(View):负责展示数据给用户,并且提供交互操作。视图通常是用户与应用程序交互的主要界面,如Web页面、桌面应用程序的窗口等。
  • 代理(Proxy):作为“中间人”,实现模型和视图之间的沟通。代理通常是一些中间件或者控制器,用于管理模型和视图之间的通信流程,以确保它们之间的正确性和可靠性。

MVC架构中,模型、视图、代理之间的关系如下图所示:

当用户与视图交互时,视图会向代理发送请求,代理会将请求转发给模型进行处理。模型完成数据的处理后,将结果返回给代理,代理再将结果传递给视图,视图最终显示给用户。在这个交互过程中,代理扮演着重要的角色,它不仅负责将请求传递给模型,还需要处理模型返回的数据,以便视图能够正确地显示数据。

 

模型 model

InterView框架中所有模型都基于抽象基类QAbstractItemModel类,InterView框-架中所有模型都基于抽象基类QAbstractltemModel类,此类由:QAbstractListModel ;QAbstractTableModel和QAbstractProxyModel类继承。

用于将数据存储在特定格式中并提供访问和操作这些数据的方法。它们实现了Qt Model/View体系结构的核心,允许在用户界面中呈现数据。Qt提供了多种类型的model,包括列表、表格、树形结构等。通过使用标准接口来访问model,可以轻松地进行数据排序、过滤、插入、修改和删除操作。Model通常与view(视图)搭配使用,以便在GUI中显示数据。常用的model有QStandardItemModel、QSqlQueryModel、QFileSystemModel等。

视图 View

InterView框架中的所有视图都基于抽象基类QAbstractltemView类,此类由QColumnView、QHeaderView、QListView、QTableView和QTreeView类继承。

Qt中的View是指数据可视化的组件,用于将model中的数据以某种方式呈现给用户。View通常与model搭配使用,以便在GUI中显示数据。Qt提供了多种类型的view,包括列表、表格、树形结构等。通过使用标准接口来访问view,可以轻松地对其进行设置和定制,如更改列宽度、行高度、排序、过滤等。常用的view有QTableView、QListView、QTreeView等。

对于不同类型的view,Qt还提供了各种内置功能和自定义选项,例如:QTableView提供了单元格编辑、复选框、进度条等;QListView提供了图标、文本、列表、网格等不同的显示方式;QTreeView提供了可展开的树形结构和可收缩的节点等。此外,还可以通过实现自定义view来创建特定需求的数据可视化组件。

代理 Delegate

InterView框架中的所有代理都基于抽象基类QAbstractltemDelegate类,
此类由QltemDelegate和QStyledltemDelegate类继承。

Delegate(代理)是Qt中非常重要的一种机制,它提供了灵活的控件定制和事件处理能力。Delegate通常用于为模型提供自定义渲染和编辑,并且可以处理与控件交互相关的事件。

在Qt中,每个控件都有一个默认的delegate,但是这个delegate只提供了基本的呈现和编辑功能。如果需要更多的定制,就需要使用自定义delegate了。

自定义delegate通常继承自QStyledItemDelegate或QAbstractItemDelegate类。QStyledItemDelegate提供了一些方便的函数来绘制和编辑数据项,而QAbstractItemDelegate则提供了更高级的控制能力。

自定义delegate需要实现以下三个函数:

  • paint():用于绘制数据项的外观。
  • createEditor():用于创建编辑器,以便用户编辑数据项。
  • setEditorData()和setModelData():用于将数据从编辑器传输到模型,以及从模型传输到编辑器。

除了这些核心函数外,还可以通过其他一些函数来控制delegate的外观和行为,例如sizeHint()、updateEditorGeometry()等。

 举例(Table)

 

//Modelextended.h
#ifndef MODELEXTENDED_H
#define MODELEXTENDED_H
#include <QAbstractTableModel>
#include <QVector>
#include <QStringList>
#include <QMap>
 
class ModelExtended : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit ModelExtended(QObject *parendt=0);
 
    //系统自带的model相关的函数进行重新定义
    virtual int rowCount(const QModelIndex &parent=QModelIndex())const; //
    virtual int columnCount(const QModelIndex &parent=QModelIndex())const; //
    QVariant data(const QModelIndex &index,int role) const; //显示数据
    QVariant headerData(int section,Qt::Orientation orientateion,int role) const; //设置表头数据
 
 
 
private:
    //QVector向量容器 QVector是Qt对所有数组的封装
    QVector<short> empindex;  //短整型数组
    QVector<short> empnameindex;
 
    //Qmap是qt通用容器,存储(键,值),并提供与键相关联值的的快速查找 是按键的ASCII码排序存储的
    QMap<short,QString> empno; //存放员工编号
    QMap<short,QString> empname;//存放员工姓名
 
 
    //Qstringlist提供一个字符串列表
    //QStringlist 添加QString 字符串,直接用<<来添加字符串
    QStringList viewlisttitle;//存放标题名称
    QStringList department_list; //存放员工部门
 
 
    void ModelFunc();
 
};
 
#endif // MODELEXTENDED_H
//Modelextended.cpp

#include "Modelextended.h"
 
ModelExtended::ModelExtended(QObject *parent):QAbstractTableModel(parent)
{
    //员工编号赋值
    empno[1]="2022001";
    empno[2]="2022002";
    empno[3]="2022003";
    empno[4]="2022004";
    empno[5]="2022005";
 
    //员工姓名赋值
    empname[1]="李哥";
    empname[2]="张哥";
    empname[3]="王哥";
    empname[4]="刘哥";
    empname[5]="齐哥";
 
    department_list<<"财务部"<<"研发部"<<"销售部"<<"后勤部"<<"董事会";
 
    ModelFunc(); //模型设计
 
 
 
}
void ModelExtended::ModelFunc() //模型设置
{
    //设置标题
    viewlisttitle<<"员工编号"<<"员工姓名"<<"部门";
    empindex<<1<<2<<3<<4<<5;
    empnameindex<<1<<2<<3<<4<<5;
}
 
 int ModelExtended::rowCount(const QModelIndex &parent)const //
{
     return empindex.size();  //表视图的行
}
 int ModelExtended::columnCount(const QModelIndex &parent)const //
{
    return 3;  //列数
}
QVariant ModelExtended::data(const QModelIndex &index,int role) const //显示数据
{
 
    if(!index.isValid()){  //判断index是否有效合法
        return QVariant();
    }
    if(role==Qt::DisplayRole){
        switch (index.column()) { //获取列的值
        case 0:
            return empno[empindex[index.row()]];
            break;
        case 1:
            return empname[empnameindex[index.row()]];
            break;
        case 2:
            return department_list[index.row()];
            break;
        default:
            return QVariant();
        }
    }
 
    return  QVariant();
}
QVariant ModelExtended::headerData(int section,Qt::Orientation orientateion,int role) const //设置表头数据
{
    //首先判断角色(role)和方向(orientation)。如果角色是Qt::DisplayRole(用于显示数据),
    //方向是水平方向(即列标题),那么就返回对应列的标题文本。
    if(role==Qt::DisplayRole && orientateion== Qt::Horizontal){
        return viewlisttitle[section];
 
    }
 
    return QAbstractTableModel::headerData(section,orientateion,role);
}
//main.cpp

#include "mainwindow.h"
 
#include <QApplication>
#include <Modelextended.h>  //自定义模型
#include <QTableView> //表视图
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //MainWindow w;
    // w.show();
 
    ModelExtended modeex;
    QTableView view;
    view.setModel(&modeex);
 
    //view->setWindowTitle("表视图模型测试");
    //view->resize(600,500);
 
    view.show();
 
 
 
    return a.exec();
}