目录
0. 前言
在上一篇文章中,我们讲了QTableView的优雅使用教程,强调了要优雅地使用QTableView,就要好好设计自己的Model类。
然后,上篇文章还发生了神奇的事情:系列文章迎来了第一条评论!!!

锣鼓喧天,鞭炮齐鸣~这不得触发一下支线任务,尝试解决一下这位朋友的提问?( 反正下一篇该写的Delegate还没看懂 )
所以本文内容旨在给出一个思路和关键代码,以实现翻页的QTableView效果。中间会提到思路形成的过程等,仅供参考~如果朋友们有更精妙的思路,欢迎评论/私信提出,共同探讨!
系列文章回顾:
Qt Model/View 学习(1) - 是什么和为什么?
Qt Model/View 学习(2) - QModelIndex索引模型数据
Qt Model/View 学习(3) - 索引来一堆东西,究竟取谁(ItemDataRole)?
Qt Model/View 学习(4) - 实现自己的QAbstractTableModel类(支持显示与修改)
Qt Model/View 学习(5) - QTableView(优雅)使用教程(附源码)
1. 思路
朋友的提问是:用QAbstractTableModel和QTableView做翻页显示,而不是用滚动条的形式。
从上一篇文章我们了解到,QTableView继承了QAbstractScrollArea,天然地就支持滚动条,但这里不让用滚动条。
但是,我们其实可以假装没用滚动条:界面上看起来是翻页效果,但逻辑还是用的滚动条在做。
这个思路的关键步骤就是,让滚动条一次的步子迈大一些,刚好跳过一页的内容,就像下图这样,红框是当前显示的内容,只要计算出每一步的步长应该就OK了。

大概想一想,需要做的事情有:
- 从
QAbstractTableModel派生自己的Model类,填好数据结构以及每页显示的行数和对应接口; - 从
QTableView派生自己的View类,重写滚动条函数wheelEvent(),使之刚好跳过整整一页;其中需要使用model()接口,获取到Model类指针,转换成自己的Model类后获取每页行数,从而计算每一页要滚动的步长; - 在
View类中添加切换页面的接口,将该接口与软件界面的某些按键关联起来;
感觉也不难嘛~但是随即想到了一个问题:对于QAbstractScrollArea来说,如果最后一页的内容并不够填满一页,将滚动条滑到底将显示的内容不太对劲,如下图:

那好像也不难:只要在Model类中,将行数rowCount()设置为每一页行数的倍数即可。
思路打通以后,要着手实现的时候,我陷入了沉思:不够优雅。

上篇文章才说的QTableView轻量化,这就直接打脸了,要派生QTableView,而且Model和View搅来搅去,岂止是不够优雅,简直太过寒碜!

那就立个小目标:优雅地实现翻页效果~
2. 思路2.0
既然打算优雅,那就静下心来好好地推理一下:
- 要实现翻页效果,但不能派生自己的
View类。那就意味着别想使用滚动条来跳页了。 - 不使用滚动条来跳页,那就意味着View的全部行数只能是一页想要显示的行数了,也就意味着
rowCount()返回的值也是一页显示的行数了; rowCount()返回值固定,而数据长度不固定,那就需要设计当前页显示数据的逻辑了,意味着data()函数需要按照当前页码来选择对应数据来显示;- ???好像已经通了!!!
核心思路就是:总行数固定不变,根据当前页码显示对应的数据~
这个思路有得搞,可以优雅起来的样子,我们撸一下代码~
3. 代码实现
我们从上一篇文章实现效果的基础上进行修改(上篇文章的源码在此处),一步步修改MyTableModel类,实现这个翻页效果。
3.1 修改行数处理
首先,添加翻页所需要的变量,修改每页要显示的行数:
public:
virtual int rowCount(const QModelIndex &/*parent*/ = QModelIndex()) const override
{
// 改为每页行数
return pageRowCount;
}
virtual int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const override
{
// 书本属性值数量
return titles.size();
}
private:
// 每页显示的数量
int pageRowCount = 5;
// 当前是第几页
int currentPage = 0;
3.2 修改数据获取
QTableView通过Model类的data()函数获取数据,修改该函数,返回跳过前面页面所有数据的偏移数据:
// 核心函数,View类从Model中取数据,传入的参数在之前的文章中有介绍
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
{
if(!index.isValid() || index.column()>=columnCount() || index.row()>=rowCount()) return QVariant();
// 根据当前页面,计算偏移
int offset = currentPage*pageRowCount;
// 再次判断
if(index.row() + offset >= bookList.size()) return QVariant();
switch(role)
{
// 显示数据用
case Qt::DisplayRole:
switch(index.column())
{
case 0:
return bookList[index.row() + offset].name;
break;
case 1:
return bookList[index.row() + offset].publisher;
break;
case 2:
return bookList[index.row() + offset].type;

本文详细描述了如何在Qt Model/View框架中,通过修改QAbstractTableModel和QTableView,实现数据驱动的翻页效果,避免直接使用滚动条,保持界面的优雅。涉及行数处理、数据获取、翻页逻辑和界面交互的实现细节。
最低0.47元/天 解锁文章
2209





