学习目标: 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)