Qt Model/View 学习(5.5) - 使用QTableView(优雅地)实现翻页效果(附源码)

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


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. 思路

朋友的提问是:用QAbstractTableModelQTableView翻页显示,而不是用滚动条的形式。

上一篇文章我们了解到,QTableView继承了QAbstractScrollArea,天然地就支持滚动条,但这里不让用滚动条。

但是,我们其实可以假装没用滚动条:界面上看起来是翻页效果,但逻辑还是用的滚动条在做。

这个思路的关键步骤就是,让滚动条一次的步子迈大一些刚好跳过一页的内容,就像下图这样,红框是当前显示的内容,只要计算出每一步的步长应该就OK了。
在这里插入图片描述
大概想一想,需要做的事情有:

  1. QAbstractTableModel派生自己的Model类,填好数据结构以及每页显示的行数和对应接口
  2. QTableView派生自己的View类,重写滚动条函数wheelEvent(),使之刚好跳过整整一页;其中需要使用model()接口,获取到Model类指针,转换成自己的Model类后获取每页行数,从而计算每一页要滚动的步长;
  3. View类中添加切换页面的接口,将该接口与软件界面的某些按键关联起来;

感觉也不难嘛~但是随即想到了一个问题:对于QAbstractScrollArea来说,如果最后一页的内容并不够填满一页,将滚动条滑到底将显示的内容不太对劲,如下图:

在这里插入图片描述
那好像也不难:只要在Model类中,将行数rowCount()设置为每一页行数的倍数即可。

思路打通以后,要着手实现的时候,我陷入了沉思:不够优雅
在这里插入图片描述
上篇文章才说的QTableView轻量化,这就直接打脸了,要派生QTableView,而且ModelView搅来搅去,岂止是不够优雅,简直太过寒碜!
在这里插入图片描述

那就立个小目标:优雅地实现翻页效果~

2. 思路2.0

既然打算优雅,那就静下心来好好地推理一下:

  1. 要实现翻页效果,但不能派生自己的View。那就意味着别想使用滚动条来跳页了。
  2. 不使用滚动条来跳页,那就意味着View的全部行数只能是一页想要显示的行数了,也就意味着rowCount()返回的值也是一页显示的行数了;
  3. rowCount()返回值固定,而数据长度不固定,那就需要设计当前页显示数据的逻辑了,意味着data()函数需要按照当前页码来选择对应数据来显示
  4. ???好像已经通了!!!

核心思路就是:总行数固定不变,根据当前页码显示对应的数据~

这个思路有得搞,可以优雅起来的样子,我们撸一下代码~

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 TableView 的基本使用Qt 中,`QTableView` 是一种用于显示表格数据的视图组件。其核心功能依赖于 `QAbstractItemModel` 或派生自它的具体模型类(如 `QStandardItemModel`)。以下是关于如何使用 `QTableView` 进行数据展示的具体说明。 #### 数据模型的创建 为了使 `QTableView` 能够正常工作,需要先定义一个数据模型。通常情况下会使用 `QStandardItemModel` 来快速构建简单模型[^2]: ```cpp QStandardItemModel *model = new QStandardItemModel(4, 2); // 创建一个4行2列的模型 ``` 可以通过调用 `setItem()` 方法向模型中填充数据项: ```cpp model->setItem(0, 0, new QStandardItem("Row1, Column1")); model->setItem(0, 1, new QStandardItem("Row1, Column2")); model->setItem(1, 0, new QStandardItem("Row2, Column1")); model->setItem(1, 1, new QStandardItem("Row2, Column2")); ``` #### 将模型绑定到视图 一旦模型被初始化并填充值之后,就可以将其关联至 `QTableView` 实例上: ```cpp QTableView *tableView = new QTableView; tableView->setModel(model); ``` 此时,`QTableView` 已经能够自动识别模型中的行列数以及单元格内容,并按照表格形式渲染出来。 #### 自定义行为与外观调整 除了基础的数据展示外,还可以通过多种方式进一步优化用户体验。例如修改表头文字、隐藏网格线或者设置只读模式等操作均能增强控件实用性[^3]。 - **更改水平/垂直标题** 如果希望指定每列对应的描述名称,则需分别针对两组索引来完成赋值动作: ```cpp model->setHorizontalHeaderItem(0, new QStandardItem("Column A")); model->setHorizontalHeaderItem(1, new QStandardItem("Column B")); model->setVerticalHeaderItem(0, new QStandardItem("Row One")); model->setVerticalHeaderItem(1, new QStandardItem("Row Two")); ``` - **控制编辑权限** 默认状态下所有字段均可双击进入编辑状态;如果想限制某些区域不可改写的话,可通过重载相应信号槽机制达成目标效果- **美化样式配置** 利用 stylesheet 属性可轻松改变整体色调布局风格等方面特性。 #### 完整示例程序清单 下面给出一段完整的代码片段用来演示上述知识点的实际应用情况: ```cpp #include <QApplication> #include <QTableView> #include <QStandardItemModel> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 初始化标准项目模型对象实例 QStandardItemModel *model = new QStandardItemModel(4, 2); // 设置部分初始条目数值 model->setItem(0, 0, new QStandardItem("Apple")); model->setItem(0, 1, new QStandardItem("$1.99")); model->setItem(1, 0, new QStandardItem("Banana")); model->setItem(1, 1, new QStandardItem("$0.78")); // 配置横向头部标签名 model->setHorizontalHeaderItem(0, new QStandardItem("Product Name")); model->setHorizontalHeaderItem(1, new QStandardItem("Price (USD)")); // 构造表格查看器窗口部件实体 QTableView *tableView = new QTableView; // 关联两者关系链路 tableView->setModel(model); // 显示最终成果画面 tableView->show(); return app.exec(); } ```
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值