QTableView对自定义的Model排序
QTableView对自定义的Model排序
1.先看图实例来理解
QTableView,翻译过来就是表格视图,表格视图中有表头,行列等基础属性,QTableView的典型界面,如下图所示
我用工作的实例给大家演示,更形象
以上都是排序好的QTableView的效果,里面的所有数据都是自定义的Model,从数据库中获取的
2.问题来了,怎么实现排序的呢
我这里自定义的Model是继承自QAbstractTableModel
的实现的,在这里要说一下,要想把QTableView等视图玩的花,秀,就得自己写model
我用一个在工作中简单点的自定义model演示,如下,想让整个表格按第三列的领出时间,按时间先后进行排序,如下图是没有排序的效果,默认是按第一列的名称进行排序,不是我们想要的效果
我的model表头信息如下
这里的model信息都是从数据库中筛选获取的
获取到数据model之后,要将model显示在QTableView上,要想实现我们的效果,就得把获取到的model设置为排序模型,如下:
// 设置表格数据模型,增加排序模型
QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(m_model.data());
tableView->setModel(proxyModel);
为什么上面我用的是m_model.data()
呢,因为我的m_model
是共享指针,要转化为普通指针,就要调用方法.data()
最后一步,QTableView设置排序即可
//生成一个排序、筛选模型,实现排序功能或者筛选的模型
QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);
//设置源数据模型
proxyModel->setSourceModel(m_model.data());
//设置proxyModel模型
m_TableView->setModel(proxyModel);
//设置允许点击表头进行排序
m_TableView->setSortingEnabled(true);
//初始化某一列的排序,升序或者降序
m_TableView->sortByColumn(4, Qt::SortOrder::AscendingOrder);
还可以设置样式表等等,让表格更好看
QTableView对自定义的Model排序这样子就实现了
效果如下:
也可以通过点击表头对应的列,进行顺序排序
应用场景
QTableView的应用场景可就多了,它是不是很像.xlsx
表格
所以他可以通过一定的方法,转化为xlsx,导出来
应用场景还有,我们电脑的文件系统的显示
补充:Qt 的默认排序是有算法,根据不同的类型传入使用不同的算法来实现我们的想要排序功能
官方算法源码如下:
bool QStandardItem::operator<(const QStandardItem &other) const
{
const int role = model() ? model()->sortRole() : Qt::DisplayRole;
const QVariant l = data(role), r = other.data(role);
// this code is copied from QSortFilterProxyModel::lessThan()
switch (l.userType()) {
case QVariant::Invalid:
return (r.type() == QVariant::Invalid);
case QVariant::Int:
return l.toInt() < r.toInt();
case QVariant::UInt:
return l.toUInt() < r.toUInt();
case QVariant::LongLong:
return l.toLongLong() < r.toLongLong();
case QVariant::ULongLong:
return l.toULongLong() < r.toULongLong();
case QMetaType::Float:
return l.toFloat() < r.toFloat();
case QVariant::Double:
return l.toDouble() < r.toDouble();
case QVariant::Char:
return l.toChar() < r.toChar();
case QVariant::Date:
return l.toDate() < r.toDate();
case QVariant::Time:
return l.toTime() < r.toTime();
case QVariant::DateTime:
return l.toDateTime() < r.toDateTime();
case QVariant::String:
default:
return l.toString().compare(r.toString()) < 0;
}
}
可以看出排序可以分为三种:int、float、double
等这类的整形,浮点型排序,Date、Time、DateTime
这类的时间,日期排序,char、String
的字符/串排序
所以我们传值的时候,要注意类型的传递,假如你想要实现数字的排序,不能将数字转化字符串传入,这样你排序时就按字符串排了,因为传入的是QVariant型的,你传入的时候,要按照严格的类型传入,才能实现想要的排序
如下:我写了一个学生成绩表,存储在sqlite数据库里
我要将数据拿出来,就要有一个学生成绩类,里面的每一个字段对应着数据库中每个地段的类型
在数据库将数据查询完后,将数据转化为学生成绩类的相应字段
获取完数据库的所有数据后,返回,在由YC_Score
型转化为QObjetct*
型
然后重置自定义的model数据
将model数据放入排序模型中
然后将排序模型设置为m_TableView(视图)的模型,就是要看到的视图
这种必须要重写model中的data方法,这个决定了我们在视图中每一列要显示信息,在这里控制
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
ScoreModel::ScoreModel(QObject *parent):BaseTableModel(parent)
{
// 0 1 2 3 4 5 6 7 8 9 10
QStringList header = {"学号", "姓名", "年龄", "语文", "数学", "历史", "政治", "地理", "化学","物理","生物"};
setHeader(header);
}
QVariant ScoreModel::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
{
return QVariant();
}
if (role == Qt::TextAlignmentRole)
{
return Qt::AlignCenter;
}
if (role != Qt::DisplayRole)
{
return QVariant();
}
int row = index.row();
if (!(row < rowCount()))
{
return QVariant();
}
YC_Score *ScoreItem = dynamic_cast<YC_Score *>(getObject(row));
if (ScoreItem == nullptr)
{
return QVariant();
}
int column = index.column();
QVariant columnContent;
switch (column)
{
case 0:
columnContent = ScoreItem->ID;
break;
case 1:
columnContent = ScoreItem->name;
break;
case 2:
columnContent = ScoreItem->age;
break;
case 3:
columnContent = ScoreItem->chinese;
break;
case 4:
columnContent = ScoreItem->math;
break;
case 5:
columnContent = ScoreItem->history;
break;
case 6:
columnContent = ScoreItem->politics;
break;
case 7:
columnContent = ScoreItem->geography;
break;
case 8:
columnContent = ScoreItem->chemistry;
break;
case 9:
columnContent = ScoreItem->physics;
break;
case 10:
columnContent = ScoreItem->biology;
break;
default:
break;
}
return columnContent;
}
我们要显示的表格一共有十列,这里直接将内容返回即可。不要统一转化为统一的类型
在返回,因为返回值是QVariant
型的,你想怎么排序,你就返回什么类型进行填充即可。这样才能在后续的点击表头排序时,根据每一列的类型进行相适应的排序。
如我们想要最后一个科目生物分数都加十分,直接在第一个返回的这里+10即可。如下,这就是MVC数据模型视图分离的精髓,将他们分离开,保证数据间的独立性,修改模型,转化为视图显示给我们看,不影响数据。
case 10:
columnContent = ScoreItem->biology + 10;
break;
这样子就可以啦
要排序,点击一下表头相应的字段,即可顺逆序排序
好了,补充那么多