一、引言
在开发桌面应用程序时,当需要展示大量数据到表格中,一次性加载所有数据可能会导致界面卡顿、响应缓慢,甚至内存溢出。QTableView 是 Qt 框架中用于展示表格数据的强大组件,结合 QAbstractTableModel 可以实现数据的分页展示,提升用户体验和应用性能。本文将详细介绍如何通过返回数据分页的方式实现 QTableView 的数据分页功能。
二、分页原理概述
分页的核心思想是将大量数据分成多个较小的“页”,每次只加载和显示其中一页的数据。在 QTableView 中,这通常通过自定义 QAbstractTableModel 来实现。QAbstractTableModel 是一个抽象基类,需要我们重写一些关键方法,如 rowCount()、columnCount()、data() 等,以实现分页逻辑。
三、分页效果
可上下切换,修改分页大小
四、实现原理
继承 QAbstractTableModel 实现 data()
重写 data() 方法
data() 方法用于返回指定位置的数据。在分页实现中,要根据当前页码和每页显示的数据数量计算出实际数据的索引。
QVariant CRelateDataModel::data(const QModelIndex& index, int role) const
{if (!index.isValid()){return QVariant();}const int row = index.row();const int nColumn = index.column();if (nColumn < m_ModelRelatedHead.GetHeadCount()) [[likely]]{std::shared_ptr<CRelateModelData> pRelateModelData = m_pRelateModelObject->GetRecordData().at(row);if (!pRelateModelData) [[unlikely]]{return QVariant();}QModelIndex modelIndex = createIndex(row, m_ModelRelatedHead.m_vecHeadInfos[nColumn].m_nHeadID);return pRelateModelData->GetData(modelIndex, role);}return QVariant();
}
class CGC_CORE_EXPORT CRemoteTestParaDefineManager : public CRelateModelObject
数据通过继承模板关联数据基类返回数据控制
将所有数据和展示数据分开
RemoteTestParaDefineVec m_vecRemoteTestParaDefines;
RemoteTestParaDefineVec m_vecShowRemoteTestParaDefines;
实现分页控制功能,包含上一页、下一页、跳转到指定页等操作
void CRemoteTestParaDefineManager::SetPageSize(int nPageSize)
{m_nPageSize = nPageSize;m_vecShowRemoteTestParaDefines.clear();for (auto& itr : m_vecRemoteTestParaDefines){if ((int)m_vecShowRemoteTestParaDefines.size() < m_nPageSize){m_vecShowRemoteTestParaDefines.push_back(itr);}}
}int CRemoteTestParaDefineManager::GetPageSize() const
{return m_nPageSize;
}int CRemoteTestParaDefineManager::GetTotalPageSize() const
{return m_vecRemoteTestParaDefines.size() / m_nPageSize + (m_vecRemoteTestParaDefines.size() % m_nPageSize == 0 ? 0 : 1);
}void CRemoteTestParaDefineManager::SetPageNum(int nPageNum)
{m_vecShowRemoteTestParaDefines.clear();int nStart = (nPageNum - 1) * m_nPageSize;int nEnd = nPageNum * m_nPageSize;for (int i = nStart; i < nEnd && i < (int)m_vecRemoteTestParaDefines.size(); ++i){m_vecShowRemoteTestParaDefines.push_back(m_vecRemoteTestParaDefines[i]);}
}int CRemoteTestParaDefineManager::GetRecordDataCount() const
{if (m_ePageType == E_PAGE_DATA_SHOW){return m_vecShowRemoteTestParaDefines.size();}else {return m_vecRemoteTestParaDefines.size();}
}std::vector<std::shared_ptr<CRelateModelData>> CRemoteTestParaDefineManager::GetRecordData() const
{std::vector<std::shared_ptr<CRelateModelData>> vecData;if (m_ePageType == E_PAGE_DATA_SHOW){for (auto& itr : m_vecShowRemoteTestParaDefines){vecData.push_back(itr);}}else{for (auto& itr : m_vecRemoteTestParaDefines){vecData.push_back(itr);}}return vecData;
}
void CDigMeasRemoteTestWidget::on_pushButton_UpPage_clicked()
{int nPageNum = ui->lineEdit_PageNum->text().toInt();if (nPageNum == 1){return;}m_nPageNum = nPageNum - 1;m_pParaDefineManager->SetPageNum(m_nPageNum);ui->lineEdit_PageNum->setText(QString::number(m_nPageNum));ui->tableView_ParaDefineManager->ResetModel();
}void CDigMeasRemoteTestWidget::on_pushButton_DownPage_clicked()
{int nPageNum = ui->lineEdit_PageNum->text().toInt();if (nPageNum == m_pParaDefineManager->GetTotalPageSize()){return;}m_nPageNum = nPageNum + 1;m_pParaDefineManager->SetPageNum(m_nPageNum);ui->lineEdit_PageNum->setText(QString::number(m_nPageNum));ui->tableView_ParaDefineManager->ResetModel();
}void CDigMeasRemoteTestWidget::on_lineEdit_PageNum_textChanged(const QString& qstrText)
{int nPageNum = qstrText.toInt();if (nPageNum < 1 || nPageNum > m_pParaDefineManager->GetTotalPageSize()){ui->lineEdit_PageNum->setText(QString::number(m_nPageNum));return;}m_nPageNum = nPageNum;m_pParaDefineManager->SetPageNum(m_nPageNum);ui->tableView_ParaDefineManager->ResetModel();
}void CDigMeasRemoteTestWidget::on_pushButton_SetPageSize_clicked()
{if (m_pParaDefineManager){m_pParaDefineManager->SetPageSize(ui->lineEdit_PageSize->text().toInt());ui->lineEdit_PageNum->setText("1");int nTotalPage = m_pParaDefineManager->GetTotalPageSize();ui->label_PageNum->setText("/" + QString::number(nTotalPage));ui->tableView_ParaDefineManager->ResetModel();}
}
总结
通过自定义 QAbstractTableModel 并重写关键方法,可以实现 QTableView 的数据分页功能。这种方式通过返回数据分页,每次只加载和显示当前页的数据,有效减少了内存占用,提升了界面响应速度。同时,通过实现分页控制功能,用户可以方便地浏览大量数据。在实际应用中,可以根据需求调整每页显示的数据数量,进一步优化用户体验。