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()); //这句话告诉框架我改数据了,他会去刷新
}