分页是应用程序开发中常见的需求,通过分页可以实现数据的分批展示,提高用户体验。下面介绍一个自定义分页控件的基本功能:
-
显示指定数量的数据:分页控件可以根据需求设置每一页展示的数据数量,保证页面展示的数据不会过多或过少。
-
显示页码信息:分页控件可以显示当前页码、总页数等信息,让用户清楚地知道当前所在的页码和还有多少页数据可以查看。
-
点击按钮翻页:分页控件通常包含上一页和下一页的按钮,用户可以通过点击按钮实现翻页功能。
-
输入页码跳转:分页控件可以提供一个输入框,用户可以输入指定的页码并点击跳转按钮进行页面跳转。
-
边界检查:分页控件需要对页码进行边界检查,确保用户不能跳转到不存在的页码或越界。
-
数据更新后重新分页:当数据更新后,分页控件可以根据最新的数据重新计算页数和当前页码,保证分页功能的准确性。
通过实现以上功能,自定义分页控件可以方便地实现数据分页的需求,提供更好的用户体验。开发者可以根据具体的应用场景和需求来进行定制和扩展。
一、简述
分页组件是Qt框架中的一个重要组成部分,用于在用户界面中实现数据的分页显示。这个组件使得大量数据能够以更易于管理的方式呈现,提高用户体验,并减轻了系统的内存负担。我们可以利用Qt Designer来创建UI,然后通过代码实现功能,或者直接编写代码来构建分页组件。
本分页控件支持显示总页数,支持显示当前页码,支持跳转到指定页,支持显示每页数量。
二、效果
三、代码实现
1、控件实现
组件设计 PageWidget.ui
头文件PageWidget.h
#ifndef PAGEWIDGET_H
#define PAGEWIDGET_H
#include <QWidget>
#include <QList>
class QLabel;
class QEvent;
namespace Ui {
class PageWidget;
}
class PageWidget : public QWidget {
Q_OBJECT
public:
explicit PageWidget(int recordCount = 20,int blockSize = 3, QWidget *parent = 0);
~PageWidget();
int getBlockSize() const;
int getMaxPage() const;
int getCurrentPage() const;
// 其他组件只需要调用这两个函数即可
void setMaxPage(int maxPage); // 当总页数改变时调用
void setCurrentPage(int currentPage, bool signalEmitted = false); // 修改当前页时调用
void showLeft();
protected:
virtual bool eventFilter(QObject *watched, QEvent *e);
signals:
void currentPageChanged(int page);
void recordCountChanged(int PageRecordCount);
private:
Ui::PageWidget *ui;
int blockSize;
int maxPage; //总页数
int currentPage; //当前页面
QList<QLabel *> *pageLabels;
int PageRecordCount; //每页显示的记录数量
void setBlockSize(int blockSize);
void updatePageLabels();
void initialize();
void setRecordCount();
};
#endif // PAGEWIDGET_H
实现代码PageWidget.cpp
#include "PageWidget.h"
#include "ui_PageWidget.h"
#include <QtGlobal>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QDebug>
#include <QIntValidator>
PageWidget::PageWidget(int recordCount,int blockSize, QWidget *parent) : QWidget(parent),
ui(new Ui::PageWidget) {
ui->setupUi(this);
// 分页组件的css
QString qss = QString(".QLabel[page=\"true\"] { padding: 1px; }")
+ QString(".QLabel[currentPage=\"true\"] { color: rgb(190, 0, 0);}")
+ QString(".QLabel[page=\"true\"]:hover { color: white; border-radius: 4px; background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(53, 121, 238, 255), stop:1 rgba(0, 202, 237, 255));}");
this->setStyleSheet(qss);
setBlockSize(blockSize);
initialize();
maxPage = 0;
setMaxPage(1);
ui->pageLineEdit->setText(QString::number(1));
PageRecordCount = recordCount;
ui->spinBox->setValue(PageRecordCount);
ui->spinBox->installEventFilter(this);
}
PageWidget::~PageWidget() {
delete ui;
delete pageLabels;
}
bool PageWidget::eventFilter(QObject *watched, QEvent *e) {
if (e->type() == QEvent::MouseButtonRelease) {
int page = -1;
if (watched == ui->previousPageLabel) { page = getCurrentPage() - 1; }
if (watched == ui->nextPageLabel) { page = getCurrentPage() + 1; }
for (int i = 0; i < pageLabels->count(); ++i) {
if (watched == pageLabels->at(i)) {
page = pageLabels->at(i)->text().toInt();
break;
}
}
if (-1 != page) {
setCurrentPage(page, true);
return true;
}
}
if (watched == ui->pageLineEdit && e->type() == QEvent::KeyRelease) {
QKeyEvent *ke = static_cast<QKeyEvent *>(e);
if (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)
{
int page = ui->pageLineEdit->text().toInt();
if(page > maxPage)
{
page = maxPage;
ui->pageLineEdit->setText(QString::number(page));
}
setCurrentPage(page, true);
return true;
}
}
if (watched == ui->spinBox && e->type() == QEvent::KeyRelease) {
QKeyEvent *ke = static_cast<QKeyEvent *>(e);
if (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)
{
int recordCount = ui->spinBox->value();
if(PageRecordCount != recordCount)
{
ui->pageLineEdit->setText(QString::number(1));
PageRecordCount = recordCount;
emit recordCountChanged(PageRecordCount);
}
return true;
}
}
return QWidget::eventFilter(watched, e);
}
int PageWidget::getBlockSize() const {
return blockSize;
}
int PageWidget::getMaxPage() const {
return maxPage;
}
int PageWidget::getCurrentPage() const {
return currentPage;
}
void PageWidget::setMaxPage(int page) {
page = qMax(page, 1);
if (maxPage != page) {
maxPage = page;
currentPage = 1;
updatePageLabels();
}
}
void PageWidget::setCurrentPage(int page, bool signalEmitted) {
page = qMax(page, 1);
page = qMin(page, maxPage);
if (page != currentPage) {
currentPage = page;
updatePageLabels();
ui->spinBox->setValue(PageRecordCount);
ui->pageLineEdit->setText(QString::number(page));
if (signalEmitted) {
emit currentPageChanged(page);
}
}
}
void PageWidget::setBlockSize(int blockSize) {
// 为了便于计算, block size 必须是奇数, 且最小为3
blockSize = qMax(blockSize, 3);
if (blockSize % 2 == 0) {
++blockSize;
}
this->blockSize = blockSize;
}
// 初始化页码的labels
// 分成三个部分, 左...中...右
void PageWidget::initialize() {
ui->pageLineEdit->installEventFilter(this);
ui->pageLineEdit->setValidator(new QIntValidator(1, 10000000, this));
ui->nextPageLabel->setProperty("page", "true");
ui->previousPageLabel->setProperty("page", "true");
ui->nextPageLabel->installEventFilter(this);
ui->previousPageLabel->installEventFilter(this);
pageLabels = new QList<QLabel *>();
QHBoxLayout *leftLayout = new QHBoxLayout();
QHBoxLayout *centerLayout = new QHBoxLayout();
QHBoxLayout *rightLayout = new QHBoxLayout();
leftLayout->setContentsMargins(0, 0, 0, 0);
leftLayout->setSpacing(0);
centerLayout->setContentsMargins(0, 0, 0, 0);
centerLayout->setSpacing(0);
rightLayout->setContentsMargins(0, 0, 0, 0);
rightLayout->setSpacing(0);
for (int i = 0; i < blockSize * 3; ++i) {
QLabel *label = new QLabel(QString::number(i + 1));
label->setProperty("page", "true");
label->installEventFilter(this);
pageLabels->append(label);
if (i < blockSize) {
leftLayout->addWidget(label);
} else if (i < blockSize * 2) {
centerLayout->addWidget(label);
} else {
rightLayout->addWidget(label);
}
}
ui->leftPagesWidget->setLayout(leftLayout);
ui->centerPagesWidget->setLayout(centerLayout);
ui->rightPagesWidget->setLayout(rightLayout);
}
void PageWidget::updatePageLabels() {
ui->leftSeparateLabel->hide();
ui->rightSeparateLabel->hide();
if (maxPage <= blockSize * 3) {
for (int i = 0; i < pageLabels->count(); i += 1) {
QLabel *label = pageLabels->at(i);
if (i < maxPage) {
label->setText(QString::number(i + 1));
label->show();
} else {
label->hide();
}
if (currentPage - 1 == i) {
label->setProperty("currentPage", "true");
} else {
label->setProperty("currentPage", "false");
}
label->setStyleSheet("/**/");
}
return;
}
int c = currentPage;
int n = blockSize;
int m = maxPage;
int centerStartPage = 0;
if (c >= 1 && c <= n + n / 2 + 1) {
// 显示前 n * 2 个, 后 n 个: 只显示右边的分隔符
centerStartPage = n + 1;
ui->rightSeparateLabel->show();
} else if (c >= m - n - n / 2 && c <= m) {
// 显示前 n 个, 后 n * 2 个: 只显示左边的分隔符
centerStartPage = m - n - n + 1;
ui->leftSeparateLabel->show();
} else {
// 显示[1, n], [c - n/2, c + n/2], [m - n + 1, m]: 两个分隔符都显示
centerStartPage = c - n / 2;
ui->rightSeparateLabel->show();
ui->leftSeparateLabel->show();
}
for (int i = 0; i < n; ++i) {
pageLabels->at(i)->setText(QString::number(i + 1)); // 前面 n 个
pageLabels->at(n + i)->setText(QString::number(centerStartPage + i)); // 中间 n 个
pageLabels->at(3 * n - i - 1)->setText(QString::number(m - i)); // 后面 n 个
}
for (int i = 0; i < pageLabels->count(); ++i) {
QLabel *label = pageLabels->at(i);
int page = label->text().toInt();
if (page == currentPage) {
label->setProperty("currentPage", "true");
} else {
label->setProperty("currentPage", "false");
}
label->setStyleSheet("/**/");
label->show();
}
}
2、控件使用
以下是一个使用示例,创建了一个窗口,并在窗口中创建了一个QTableWidget。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "PageWidget.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void PageChanged(int page);
void RecordCountChanged(int recordCount);
private:
void init_table();
void SetPage();
void ShowData(int page);
private:
Ui::MainWindow *ui;
PageWidget *m_pPageWidget;
int m_pageRecordCount; //每页显示的记录数量
int m_currentPage; //当前页面
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_pPageWidget = new PageWidget;
connect(m_pPageWidget, &PageWidget::currentPageChanged, this, &MainWindow::PageChanged);
connect(m_pPageWidget, &PageWidget::recordCountChanged, this, &MainWindow::RecordCountChanged);
QVBoxLayout *playout = new QVBoxLayout;
playout->addWidget(m_pPageWidget);
ui->widget->setLayout(playout);
m_pageRecordCount = 20;
m_currentPage = 1;
init_table();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::PageChanged(int page)
{
ShowData(page);
}
void MainWindow::RecordCountChanged(int recordCount)
{
m_pageRecordCount = recordCount;
SetPage();
}
void MainWindow::init_table()
{
ui->tableWidget->clear();
QStringList labels;
labels<<QString("编号")<<QString("数量");
ui->tableWidget->setColumnCount(2);
ui->tableWidget->setHorizontalHeaderLabels(labels);
SetPage();
}
void MainWindow::SetPage()
{
m_pPageWidget->setMaxPage(ceil(2000.0/m_pageRecordCount)/*此处不能用整数,防止页数计算错误*/);
ShowData(1);
}
void MainWindow::ShowData(int page)
{
m_currentPage = page;
int records = (page*m_pageRecordCount > 2000) ? (2000-(page-1)*m_pageRecordCount) : m_pageRecordCount;
ui->tableWidget->setRowCount(0);
int start = (page-1)*m_pageRecordCount;
for (int i = 0; i < records; i++)
{
int rowCount = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(rowCount);
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(QString("%1").arg(start+i+1)));
ui->tableWidget->setItem(i, 1, new QTableWidgetItem("1"));
}
}
到此这篇关于Qt实现分页组件的文章就介绍到这了。
感谢阅读!希望这些内容对您有所帮助,并且能够给您带来一些启发和灵感。如果您有任何问题或想要了解更多信息,请随时联系。再次感谢您的支持和关注!祝您一切顺利!