8.2 模型(Model)
8.2 模型(Model)
在前面我们讲过,Qt中有一些内置的可以被我们直接使用的模型,当然也有一些用于模型类被继承的基类,例如QAbstractItemModel,QAbstractListModel,QAbstractTableModel,QAbstractTreeModel,QProxyModel,QStandradItemModel。
接下来我们将通过一个表格(用于描述不同军种的武器的表格)来演示一下QAbstractTableModel的使用。
(1)建立一个Qt的GUI程序,项目名称为ModelEx,不需要勾选创建ui界面。
(2)新建一个C++类,用于描述我们的模型,类名就为ModelEx,在modelex.h中添加以下的成员
#ifndef MODELEX_H
#define MODELEX_H
#include <QObject>
#include <QAbstractTableModel>
#include <QMap>
#include <QStringList>
#include <QModelIndex>
#include <QString>
#include <QVector>
class ModelEx:public QAbstractTableModel
{
Q_OBJECT
public:
public:
explicit ModelEx(QObject*parent = nullptr);
~ModelEx();
public:
virtual int rowCount(const QModelIndex& parent = QModelIndex())const;//该函数是来自QAbstractTableModel的纯虚函数,我们必须要实现它
virtual int columnCount(const QModelIndex&parent = QModelIndex())const;//同上
QVariant data(const QModelIndex&index,int role = Qt::DisplayRole)const;//返回模型中的数据
QVariant headerData(int section,Qt::Orientation orentation,int role)const;//返回模型中的表头的数据
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
private:
QVector<short> m_army;
QVector<short> m_weaponType;
QMap<short,QString> m_armyMap;
QMap<short,QString>m_weaponTypeMap;
QStringList m_weapon;
QStringList m_header;
private:
void loadModelData();
void populateModel();
};
#endif // MODELEX_H
(3)在modelex.cpp中进行以下函数的实现
#include "modelex.h"
ModelEx::ModelEx(QObject*parent)
{
loadModelData();
populateModel();
}
ModelEx::~ModelEx()
{
}
//数据一共有多少行,必须要描述清楚
int ModelEx::rowCount(const QModelIndex &parent) const
{
return m_army.size();
}
//有多少个表头列,也必须要描述清楚
int ModelEx::columnCount(const QModelIndex &parent) const
{
//由于我的数据里面一共就只有3个列,我这里就只返回3
return 3;
}
//决定数据能不能显示到界面上,最重要的就是重写这里的data方法
QVariant ModelEx::data(const QModelIndex &index, int role) const
{
/*
* role参数
enum ItemDataRole {
DisplayRole = 0,//显示文字
DecorationRole = 1,//绘制装饰数据(通常是图标)
EditRole = 2,//在编辑器中编辑的数据
ToolTipRole = 3,//工具提示
StatusTipRole = 4,//状态栏提示
WhatsThisRole = 5,//What's This 文字
SizeHintRole = 13,//尺寸提示
FontRole,//默认代理的字体来作为数据的显示字体
TextAlignmentRole,//默认代理的对其方式
BackgroundRole,//默认代理的背景画刷
ForegroundRole,//默认代理的前景画刷
CheckStateRole,//默认代理的检查框状态
UserRole//用户自定义的数据其实位置
*/
if(!index.isValid())
{
return QVariant();
}
else
{
switch (index.column())//我这里是需要根据列,来返回对应的列的数据某一行的数据
{
case 0://0索引就是军种
return m_armyMap[index.row()];
break;
case 1://1对应了武器的种类
return m_weaponTypeMap[index.row()];
break;
case 2://2对应了武器的具体名称
return m_weapon[index.row()];
break;
default:
return QVariant();
break;
}
}
}
QVariant ModelEx::headerData(int section, Qt::Orientation orentation, int role) const
{
if(Qt::DisplayRole&&orentation == role && Qt::Horizontal == orentation)
{
return m_header[section];
}
return QAbstractTableModel::headerData(section,orentation,role);
}
bool ModelEx::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(!index.isValid())
{
return false;
}
else
{
switch (index.column())
{
case 0:
m_armyMap.operator[](index.row()) = value.toString();
break;
case 1:
m_weaponTypeMap.operator[](index.row()) = value.toString();
break;
case 2:
m_weapon.operator[](index.row()) = value.toString();
break;
}
return true;
}
}
void ModelEx::loadModelData()
{
m_armyMap[0] = "空军";
m_armyMap[1] = "海军";
m_armyMap[2] = "陆军";
m_armyMap[3] = "海军陆战队";
m_armyMap[4] = "海军";
m_armyMap[5] = "海军陆战队";
m_armyMap[6] = "陆军";
m_armyMap[7] = "空军";
m_weaponTypeMap[0] = "轰炸机";
m_weaponTypeMap[1] = "战斗机";
m_weaponTypeMap[2] = "航空母舰";
m_weaponTypeMap[3] = "驱逐舰";
m_weaponTypeMap[4] = "直升机";
m_weaponTypeMap[5] = "坦克";
m_weaponTypeMap[6] = "两栖攻击舰";
m_weaponTypeMap[7] = "两栖战车";
}
//插入数据到容器中
void ModelEx::populateModel()
{
m_header << "军种" << "种类" << "武器";
m_army << 1 << 2 << 3 << 4 << 2 << 4 << 3 << 1;
m_weaponType << 1 << 3 << 5 << 7 << 4 << 8 << 6 << 2 ;
m_weapon << "B-2" << "尼米兹级" << "阿帕奇" << "黄蜂级" << "阿利伯克级" << "AAAV" << "M1A1" << "F-22";
}
(4)修改main.cpp中的内容为
#include "mainwindow.h"
#include <QApplication>
#include <QTableView>
#include <QModelIndex>
#include "modelex.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ModelEx model;
QTableView tableView;
tableView.setModel(&model);
tableView.show();
return a.exec();
}
(5)运行效果

小结:
本节我们通过自己写一个模型类来继承自Qt的QAbstractTableModel类来实现了一个自定义的模型,实际上关于这里面我们需要知道的是,我们在继承的QAbstractTableModel中的过程中,由于这个抽象的表格类模型类中有几个纯虚函数,因此我们务必要去实现他们,它们分别是:
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const = 0 //一个表格模型中,模型数据又多少个列必须是要被说明的
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const = 0 //一个表格模型中,一共有多少行的数据,也必须要被说明清楚
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const = 0 //data方法是最重要的一环,我们需要通过具体的数据,并根据表格的列数来往里面填充入数据项,一般按照以下的套路格式来即可
if(!index.isValid())
{
return QVariant();
}
else
{
switch(index.column())
{
case 0://对应的表头项的索引
dataInsert();///
break;
case 1:
///
///
///
.
.
.
}
}
本节代码:https://files.cnblogs.com/files/blogs/792763/ModelEx.zip?t=1719156158&download=true

浙公网安备 33010602011771号