学习目标: interView理解和自定义模型操作
前置环境
运行环境:qt creator 4.12
学习内容:
interView是一个具有插件架构的Qt应用程序框架,它旨在提供一个易于扩展和定制的应用程序开发解决方案。
在interView框架中,这三者协作的方式如下:
视图类从模型类获取数据,并使用委托类来绘制和编辑数据单元格。
用户与视图进行交互(如点击、编辑等),视图类会通知模型类进行相应的数据更新。
模型类更新数据后,会通知视图类进行重绘,视图类会再次使用委托类来绘制新的数据。
在 Qt 的模型-视图架构中,这三个抽象类扮演着重要的角色:
-
视图类 (QAbstractItemView):
- 视图类负责显示和管理数据项目。
- 常见的视图类有
QListView
、QTreeView
、QTableView
等。 - 视图类从模型类获取数据,并负责将数据项目渲染到屏幕上。
- 视图类还负责处理用户交互,如鼠标点击、拖拽等操作。
-
模型类 (QAbstractItemModel):
- 模型类负责存储和管理数据。
- 常见的模型类有
QStringListModel
、QFileSystemModel
、QStandardItemModel
等。 - 模型类提供了标准的接口,如
rowCount()
、columnCount()
、data()
等,供视图类查询和操作数据。 - 模型类可以是层次结构,如
QAbstractItemModel
的子类QAbstractTableModel
。
-
委托类 (QAbstractItemDelegate):
- 委托类负责渲染和编辑数据项目。
- 常见的委托类有
QItemDelegate
、QStyledItemDelegate
等。 - 委托类负责决定如何显示和编辑数据项目,如文本、图标、下拉框等。
- 委托类还负责处理用户输入,并将编辑后的数据返回给模型类。
下面是一个具体的例子:
假设您有一个 QTableView
显示员工信息,包括名字、年龄、工资等。
- 您创建一个
QStandardItemModel
作为数据模型,存储员工信息。 - 将
QTableView
的模型设置为上述数据模型。 - 您可以创建一个自定义的
QItemDelegate
子类,负责渲染和编辑员工信息。- 例如,对于年龄字段,您可以使用一个
QSpinBox
编辑器;对于工资字段,您可以使用一个QDoubleSpinBox
编辑器。
- 例如,对于年龄字段,您可以使用一个
- 将自定义的委托类设置到
QTableView
上,这样就可以使用您定制的渲染和编辑行为了。
开发目标:
自定义模型
详细主要代码和运行测试
main
#include "mainwindow.h"
#include"modleextend.h"
#include <QApplication>
#include<QTableView>
int main(int argc, char *argv[])
{QApplication a(argc, argv);modleextend modle;QTableView view;view.setModel(&modle);view.setWindowTitle("ModelExtended模型扩展--测试操作");view.resize(500,300);view.show(); // 显示表视图return a.exec();
}
自定义模型扩展类
#ifndef MODLEEXTEND_H
#define MODLEEXTEND_H#include<QAbstractTableModel>
//自定义数据模型
class modleextend : public QAbstractTableModel
{
public://自定义数据模型explicit modleextend(QObject *parent = 0);
public:// 系统自的model相关的函数进行重新定义virtual int rowCount(const QModelIndex &parent=QModelIndex()) const; // 行virtual int columnCount(const QModelIndex &parent=QModelIndex()) const; // 列virtual QVariant data(const QModelIndex &index,int role) const; // 显示数据virtual QVariant headerData(int section,Qt::Orientation orientateion,int role) const; // 设置表头数据
private:QVector<short> index;QVector<short> id;QMap<short,QString> id_index;QMap<short,QString> name_index;QStringList view_title;
};#endif // MODLEEXTEND_H
详细实现
#include "modleextend.h"modleextend::modleextend(QObject *parent):QAbstractTableModel(parent)
{id_index[1]="2022001";id_index[2]="2022002";id_index[3]="2022003";id_index[4]="2022004";id_index[5]="2022005";name_index[1]="张三";name_index[2]="李四";name_index[3]="王五";name_index[4]="刘山";name_index[5]="张平";index<<1<<2<<3<<4<<5;view_title<<"员工号"<<"姓名";
}
int modleextend::rowCount(const QModelIndex &parent) const {return index.size();
}int modleextend::columnCount(const QModelIndex &parent) const {return view_title.size();
}// 显示数据 index 参数指定了要查询的单元格位置,role 参数指定了要获取的数据的角色
QVariant modleextend::data(const QModelIndex &index,int role) const{if(!index.isValid())return QVariant();//检查了角色是否为Qt::DisplayRole(即数据显示角色)。这个角色通常用于返回需要显示在视图中的文本数据。if(role==Qt::DisplayRole){switch (index.column()) {case 0:return id_index[this->index[index.row()]];break;case 1:return name_index[this->index[index.row()]];break;default:return QVariant();}}
}// 返回表头数据 index 参数指定了要查询的行或列索引,orientation 参数指定了表头的方向(水平或垂直),role 参数指定了要获取的数据的角色。
QVariant modleextend::headerData(int index,Qt::Orientation orientateion,int role) const{if(role==Qt::DisplayRole && orientateion==Qt::Horizontal)return view_title[index];//调用父类QAbstractTableModel的headerData()函数,让父类来处理表头数据的返回。return QAbstractTableModel::headerData(index,orientateion,role);}
总结:
模型抽象理解成磨具,视图则是往磨具注入数据的程序效果,当与视图互动时,代理作为解耦磨具和数据。
最后附上源代码链接
对您有帮助的话,帮忙点个star
21-model-view-delegate · jbjnb/Qt demo - 码云 - 开源中国 (gitee.com)