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

posted @ 2024-06-23 23:22  蜡笔小新Pointer  阅读(20)  评论(0)    收藏  举报