1.QabstractTableModel常用功能
QAbstractTableModel子类化时,必须覆写:
Int rowCount();
//返回显示的行数
int columnCount();
//返回显示的列数
Qvariant headerData(int section, Qt::Orientation orientation, int role);
//返回标题role角色对应的值
// section:段号,从0开始,对于Qt::Horizontal水平标题,则是每列的标题名,对于Qt::Vertical垂直标题,则是每行的左侧标题名
//orientation:标题类型
//role:对应值是Qt:: ItemDataRole枚举, 对于role角色,常用的有:
//Qt::DisplayRole :以文本方式显示数据(QString)
//Qt::DecorationRole :将数据作为图标来装饰(QIcon,QPixmap)
//Qt::EditRole :可编辑的数据信息显示(QString)
//Qt::ToolTipRole :作为工具提示显示(QString)
//Qt::StatusTipRole :作为状态栏中显示的数据(QString)
//Qt::WhatsThisRole :作为帮助信息栏中显示的数据(QString)
//Qt::FontRole :设置字体(QFont)
//Qt::TextAlignmentRole :设置模型数据的文本对齐(Qt::AlignmentFlag)
//Qt::BackgroundRole :设置模型数据的背景色(QBrush)
//Qt::ForegroundRole : 设置模型数据的前景色,比如字体(QBrush)
//Qt::SizeHintRole : 设置模型数据的大小
QVariant data(const QModelIndex &index, int role);
//返回index单元格下的role角色数据。通过index可以获取行号和列号
bool setData(const QModelIndex &index, const QVariant &value, int role);
//将index单元格下的role角色设置为value
//对于可编辑模型,必须重写该函数,然后还需要重写flags()
//返回值为true:表示设置成功,然后还需要显式发射dataChanged信号
2.QabstractTableModel可编辑功能
如果不想实现QabstractTableModel可编辑功能, 则调用QTableView ->setEditTriggers(QAbstractItemView::NoEditTriggers)即可.
如果要实现的话,则需要覆写下面函数:
Qt::ItemFlags flags(const QModelIndex &index);
//设置每个单元格的flag,对于可编辑模型,必须重写它,添加Qt::ItemIsEditable(可编辑属性)
//然后当我们双击时,会默认创建一个编辑组件(这是由 delegate 完成的)然后delegate会调用QAbstractTableModel ::data(index, Qt::EditRole)读取默认编辑值
//当我们编辑完成后, delegate会调用QAbstractTableModel :: setData (index, value, Qt::EditRole)告诉我们是否保存数据.
如果对于可调整行列的模型,可以重写insertRows()、removeRows()、insertColumns()、removeColumns().在实现这些函数时,还需要调用合适的父类函数,用来通知model调整了哪些内容:
insertRows():
//在向数据结构插入新行之前需要调用父类的beginInsertRows(),并且必须在之后立即调用endInsertRows()。
insertColumns():
//在向数据结构插入新列之前需要调用父类的beginInsertColumns(),并且必须在之后立即调用endInsertColumns()。
RemoveRows():
//在删除行之前需要调用父类的beginRemoveRows(),并且必须在之后立即调用endRemoveRows()。
RemoveColumns():
//在删除列之前需要调用父类的beginRemoveColumns(),并且必须在之后立即调用endRemoveColumns()。
注意:如果要重新刷新model数据,则必须在刷新model之前调用beginResetModel(),然后刷新之后调用endResetModel。
或者在刷新之后,emit dataChanged(index(0,0),index(rowCount,columnCount))来进行刷新视图
3.model排序之重写sort方法
首先需要调用QtableView->setSortingEnabled(true)使能排序,sort函数声明如下所示:
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
//当用户点击标题进行降序/升序排序时,会调用该方法
//或者调用QtableView->sortByColumn()时,也会调用该方法
// column:第几列进行排序
// order:升序(AscendingOrder)、降序(DescendingOrder)
排序方法则使用std::sort()来实现.然后写个sort类来配合column和order实现排序.
进行排序的时候,必须得调用beginResetModel(),endResetModel()进行界面刷新.
4.代码实现
界面如下所示,支持自定义排序:
下载链接:https://download.csdn.net/download/qq_37997682/13709956
custommodel.h如下所示
#ifndef CUSTOMMODEL_H
#define CUSTOMMODEL_H
#include <QObject>
#include <QAbstractTableModel>
#include <QModelIndex>
#include <QFont>
#include <QPixmap>
//排序类
class DataSort
{
public:
int mColumn;
Qt::SortOrder mSortOrder;
DataSort(int column, Qt::SortOrder order)
: mColumn(column)
, mSortOrder(order)
{}
bool operator()(const QVector<QString>* v1, const QVector<QString>* v2)
{
int compare = 0; //>0:大于 <0:小于
bool ret=false;
switch ( mColumn )
{
case 0 : //序号,需要判断数字
case 3 : //信号ID,需要判断数字
compare = v1->at(mColumn).toInt() - v2->at(mColumn).toInt();
break;
default : //其它,只判断字符串
compare = v1->at(mColumn).compare(v2->at(mColumn));
break;
}
if(compare==0) //相等必须返回flase,否则的话,对于一列相同的值进行降序,那么会一直返回true,从而死循环
{
return false;
}
else
ret = compare>0?false:true;
if ( mSortOrder == Qt::DescendingOrder ) //降序
{
ret = !ret;
}
return ret;
}
};
class CustomModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit CustomModel(QAbstractTableModel *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
Qt::ItemFlags flags(const QModelIndex &index) const;
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
public slots:
void UpdateData(void);
private:
QList<QVector<QString> * > m_data;
int m_columnCount;
int m_rowCount;
QFont m_Font;
QPixmap m_icon;
signals:
};
#endif // CUSTOMMODEL_H
custommodel.cpp如下所示:
#include "custommodel.h"
#include <QDateTime>
#include <QDebug>
CustomModel::CustomModel(QAbstractTableModel *parent) : QAbstractTableModel(parent)
{
m_columnCount = 5; //5行
m_rowCount = 60;
m_Font.setFamily("Microsoft Yahei");
m_Font.setPixelSize(17);
m_icon.load(":alarm");
m_icon = m_icon.scaled(20,22,Qt::KeepAspectRatio,Qt::SmoothTransformation);
UpdateData();
}
void CustomModel::UpdateData(void)
{
beginResetModel();
int count = m_data.size();
if(count > 0)
{
for(int i = 0; i < count; i++)
{
delete m_data.at(i);
}
m_data.clear();
}
for (int i = 0; i < m_rowCount; i++) {
QVector<QString>* line = new QVector<QString>(m_columnCount);
line->replace(0,QString("%1").arg(i+1));
line->replace(1,"显示器");
line->replace(2,"未显示");
line->replace(3,QString("%1").arg(qrand()%100));
line->replace(4,QDateTime::currentDateTime().addDays(-10).toString("hh:mm:ss"));
m_data.append(line);
}
endResetModel();
//emit dataChanged(index(0,0),index(m_data.count()-1,columnCount()-1)); //和beginResetModel()、endResetModel() 本质一样
}
int CustomModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent) //由于parent未使用,所以通过Q_UNUSED去掉编译警告
return m_data.count();
}
int CustomModel::columnCount(const QModelIndex &parent) const //列
{
Q_UNUSED(parent)
return m_columnCount;
}
QVariant CustomModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal) {
switch (section) {
case 0 :
return "序号";
case 1 :
return "设备";
case 2 :
return "状态";
case 3 :
return "信号ID";
case 4 :
return "上报时间";
default :
return "";
}
} else {
return QString("%1").arg(section + 1);
}
}
QVariant CustomModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole) { //显示内容
return m_data[index.row()]->at(index.column());
} else if (role == Qt::EditRole) { //正在启动编辑,返回当前默认编辑值
return m_data[index.row()]->at(index.column());
} else if (role == Qt::TextAlignmentRole) { //内容排版
return Qt::AlignCenter;
} else if (role == Qt::FontRole) { //字体
return m_Font;
} else if (role == Qt::DecorationRole) { //图标
if (index.column() == 2)
return m_icon;
}
return QVariant();
}
bool CustomModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::EditRole) { //编辑完成,保存数据到model,并返回true
m_data[index.row()]->replace(index.column(), value.toString());
emit dataChanged(index, index); //重新实现setData()函数时,必须显式发出该信号。
return true;
}
return false;
}
Qt::ItemFlags CustomModel::flags(const QModelIndex &index) const
{
return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; //设置item可编辑
}
void CustomModel::sort(int column, Qt::SortOrder order)
{
beginResetModel();
DataSort comp(column,order);
std::sort(m_data.begin(), m_data.end(),comp);
endResetModel();
}