QAbstractTableModel使用详解&数据单条更新&整体更新

1、入门

实现一个最简单的model需要实现如下函数

//QTableView使用model的时候,根据这个函数获取表格有多少行。
virtual int    rowCount(const QModelIndex & parent = QModelIndex()) const;  
//QTableView使用model的时候,根据这个函数获取表格有多少列。
virtual int columnCount(const QModelIndex & parent = QModelIndex()) const;
//QTableView使用model的时候,根据这个函数获取单元格的数据。
virtual QVariant    data(const QModelIndex & index, int role = Qt::DisplayRole) const;
//QTableView使用model的时候,根据这个函数获取表头的数据,自己可以实现水平表头和垂直表头数据。
virtual QVariant    headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;

model实现完成之后,设置给QTableView,假设 QTableView *table = new QTableView;

CustomTableModel * model = New CustomTableModel(table);
table->setModel(model);

//想table好看点就需要做一些设置,列举一点,根据需要自己选用
table->verticalHeader()->setVisible(false);    //设置垂直表头不可见
table->setEditTriggers(QAbstractItemView::AllEditTriggers);    //任意动作都可出发编辑
table->resizeColumnsToContents();    //设置表格的列宽以内容宽度为准
table->horizontalHeader()->setResizeMode(QHeaderView::Stretch);    //设置表头可拉伸,这样的话会填充整个画面可填充宽度。

2、进阶

数据的整体更新,单条更新,单条插入,单条删除等,参考代码如下。

想更新的时候,就直接调用model接口就行

QList<CustomTableItem> list = ;    //你需要更新的 items
model->updateAllItems(list);

CustomTableModel.h中的实现如下

写一个最基本的tablemodel给Qtableview用,需要重写如下几个函数。

//自定义数据存储格式,如果数据比较简单,就不需要这个数据结构。
//这里支持四个字段,属性名(strPropertyName),属性值(strPropertyValue),属性值的类型(strPropertyType),属性值的范围(strPropertyRange)。
struct CustomTableItem
{
    CustomTableItem(const QString &_strName, const QVariant &_strValue, const QString &_strType, const QString &_strRange)
:strPropertyName(_strName),strPropertyValue(_strValue),strPropertyType(_strType),strPropertyRange(_strRange)
    QString strPropertyName;
    QString strPropertyValue;
    QString strPropertyType;
    QString strPropertyRange;
};

class CustomTableModel :public QAbstractTableModel
{
    Q_OBJECT
public:
    enum CustomColumn {
        CustomColumn_PropertyName = 0,
        CustomColumn_PropertyValue,
    }
    enum CustomRole {
        CustomRole_PropertyType = Qt::DisplayRole + 300,//只要不与Qt重复即可
        CustomRole_PropertyType = Qt::DisplayRole + 301,
    }

    CustomTableModel(QObject *parent);
    ~CustomTableModel();

    //来自QAbstractTableModel的父类QAbstractItemModel的几个虚函数需要实现

    //QTableView使用model的时候,根据这个函数获取表格有多少行。
    virtual int	rowCount(const QModelIndex & parent = QModelIndex()) const;  
  
     //QTableView使用model的时候,根据这个函数获取表格有多少列。
    virtual int columnCount(const QModelIndex & parent = QModelIndex()) const; 

     //QTableView使用model的时候,根据这个函数获取单元格的数据。
    virtual QVariant	data(const QModelIndex & index, int role = Qt::DisplayRole) const;

    //QTableView使用model的时候,根据这个函数获取表头的数据,自己可以实现水平表头和垂直表头数据。
    virtual QVariant	headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;

    //这个是可选函数,如果表格使用了渲染即delegate,那么这个函数可以设置哪一些行列可以编辑。
    virtual Qt::ItemFlags	flags(const QModelIndex & index) const;


    //自定义函数
    //更新所有数据,假设传入的数据就是和model定义的数据相同,这里不同也没关系,可以自己在函数里面写解析数据就行。
    void updateAllItems(const QList<CustomTableItem> &allitems);
    //更新单条数据,分为三种,插入,删除,更新
    void insertSingleItem(const QModelIndex &index,const CustomTableItem &item) ;   //插入
    void deleteSingleItem(const QModelIndex &index,const CustomTableItem &item) ;   //删除
    void updateSingleItem(const QModelIndex &index,const CustomTableItem &item) ;   //更新

private:
    QList<CustomTableItem> m_data;    //数据
    QStringList m_horizontalHeader;    //自定义水平表头,有需要才定义
    QStringList m_verticalHeader;        //自定义水平表头,有需要才定义

};

CustomTableModel.cpp中的实现如下

//函数的作用这里不细说了,在CustomTableModel.h文件里面已经有说明了

CustomTableModel::CustomTableModel(QObject *parent):QAbstractTableModel(parent)
{
    //水平表头追加内容,加了两列
    m_horizontalHeader << tr("元件属性名") << tr("元件属性值");
    //垂直表头类似,自己可以加,此处我就不加了
    //m_verticalHeader<< tr("xxxxx") << tr("xxxxx");
}

CustomTableModel::~CustomTableModel() {}


//QTableView使用model的时候,根据这个函数获取表格有多少行。
int	CustomTableModel::rowCount(const QModelIndex & parent /*= QModelIndex()*/) const
{
    return m_data.count();
} 
  
//QTableView使用model的时候,根据这个函数获取表格有多少列。
int CustomTableModel::columnCount(const QModelIndex & parent = QModelIndex()) const
{
    return m_horizontalHeader.count();
}

//QTableView使用model的时候,根据这个函数获取单元格的数据。
QVariant	CustomTableModel::data(const QModelIndex & index, int role /*= Qt::DisplayRole*/) const
{
    if(!index.isValid()) {
        return QVariant();
    }

    int row = index.row();
    if(row < m_data.count()) {
        if(Qt::DisplayRole == role || Qt::EditRole == role) {    //可以根据role和index的行列返回需要的值,比如这些值不需要显示
            switch(index.column()) {
            case CustomColumn_PropertyName:
                return m_data[row].strPropertyName;
            case CustomColumn_PropertyValue:
                return m_data[row].strPropertyValue;
            default:
                return QVariant();
            }
        } else if(CustomRole_PropertyType == role) {    //可以根据role不同返回需要的值,比如这些值不需要显示
            return m_data[row].strPropertyType;
        } else if(CustomRole_PropertyRange == role) {    //可以根据role不同返回需要的值,比如这些值不需要显示
            return m_data[row].strPropertyRange;
        }
        
    }
    return QVariant();
}

//QTableView使用model的时候,根据这个函数获取表头的数据,自己可以实现水平表头和垂直表头数据。
QVariant	CustomTableModel::headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const
{
    if(orientation == Qt::Horizontal) {    //水平表头
        if(Qt::DisplayRole == role && section < m_horizontalHeader.count()) {
            return m_horizontalHeader[section];
        }
    } else if(orientation == Qt::Vertical) {
        //操作差不多,返回垂直表头,如果需要的话
    }
    return QAbstractTableModel::headerData(section,orientation,role);
}

//这个是可选函数,如果表格使用了渲染即delegate,那么这个函数可以设置哪一些行列可以编辑。
Qt::ItemFlags	CustomTableModel::flags(const QModelIndex & index) const
{
     if(!index.isValid()) {
        return QVariant();
    }
     if(index.column() == CustomColumn_PropertyValue) {    //设置只有value行可以编辑
        return Qt::ItemIsEnabled|Qt::ItemIsSelectable|Qt::ItemIsEditable;
    }
    return QAbstractTableModel::flags(index);
}


//自定义函数
//更新所有数据,假设传入的数据就是和model定义的数据相同,这里不同也没关系,可以自己在函数里面写解析数据就行。
void CustomTableModel::updateAllItems(const QList<CustomTableItem> &allitems)
{
    //修改数据前后,用beginResetModel()和endResetModel()。
    beginResetModel();    //通过这个告诉我要开始修改model了
    if(!index.isValid()) {
        return;
    }
    m_data.clear();
     for (int i = 0;i < allitems.count();++i) {
        m_data.append(allitems[i]);
    }
    endResetModel();    //通过这个告诉我修改model结束了
}
//更新单条数据,分为三种,插入,删除,更新
void CustomTableModel::insertSingleItem(const QModelIndex &index,const CustomTableItem &item)   //插入
{
    //插入行前后,使用beginInsertRows()和endInsertRows(),与之相同,列也是类似,插入列前后,使用beginInsertColumns()和endInsertColumns()。不过实现复杂一点
    if(!index.isValid()) {
        return;
    }
    beginInsertRows();
    m_data.insert(index.row(),item);
    endInsertRows();
}
void CustomTableModel::deleteSingleItem(const QModelIndex &index,const CustomTableItem &item)   //删除
{
    
    //删除行前后,使用beginRemoveRows()和endRemoveRows(),与之类似,删除列前后,使用beginRemoveColumns()和endRemoveColumns()。
    if(!index.isValid()) {
        return;
    }
    beginRemoveRows();
    m_data.removeAt(index.row());
    endRemoveRows();
}

void CustomTableModel::updateSingleItem(const QModelIndex &index,const CustomTableItem &item)    //更新
{
    if(!index.isValid()) {
        return;
    }
    m_data.replace(index.row(),item);
    emit dataChanged(index.sibling(index.row(),0),index.sibling(index.row(),columnCount());    //这句话告诉框架我改数据了,他会去刷新
}

  • 9
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在 QAbstractTableModel 中添加 QVector 数据,你需要重写 QAbstractTableModel 的以下函数: 1. rowCount():返回数据的行数。 2. columnCount():返回数据的列数。 3. data():返回指定索引位置的数据。 首先,在你的自定义模型类中声明一个 QVector 成员变量,用于存储数据。例如: ```cpp QVector<int> m_data; ``` 然后,在重写的函数中,根据需要处理相关逻辑。以下是一个简单的示例: ```cpp int MyTableModel::rowCount(const QModelIndex& parent) const { Q_UNUSED(parent); return m_data.size(); } int MyTableModel::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent); return 1; } QVariant MyTableModel::data(const QModelIndex& index, int role) const { if (!index.isValid() || role != Qt::DisplayRole) return QVariant(); if (index.row() >= 0 && index.row() < m_data.size()) { return m_data[index.row()]; } return QVariant(); } ``` 在这个示例中,我们假设 QVector<int> m_data 是一个包含整数数据的向量。rowCount() 函数返回向量的大小,即行数。columnCount() 函数返回 1,表示只有一列。data() 函数根据指定的索引位置返回相应的数据。 当你想要添加新的数据时,可以使用 QVector 的 append() 或 push_back() 函数将新的数据添加到向量中。例如: ```cpp m_data.append(newData); ``` 这样,当你更新模型时,视图会自动更新显示新的数据。记得在适当的地方调用模型的 dataChanged() 函数以通知视图进行更新。 希望这个示例对你有所帮助!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值