【自制软件】PDF学习宝-开发日记6--两个自定义的类

550 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情


📒博客首页:何名取 的个人主页 - 文章 - 掘金 (juejin.cn)
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
❤️期待一起交流!
🙏作者水平很有限,如果发现错误,求告知,多谢!
🌺有问题可私信交流!!!


PDF

前言

前面已经将Qt PDF模块添加到了工程中,这意味着已经可以使用Qt PDF模块来进行PDF显示功能的开发了。本节将使用三个与PDF模块有关的类,分别是QPdfDocument-PDF文档类、PageSelector-自定义的页选择类、ZoomSelector-自定义的缩放选择类。

这三个类中QPdfDocument是Qt PDF自带的类,已经定义好了,可以直接进行使用,其余的两个类则需要利用Qt PDF模块中的一些类和其他的一些通用类来自己将其实现。

创建PageSelector类

右键点击工程文件夹,弹出菜单: image.png

选择C++ Class来创建: image.png

将类名设置为PageSelector,并选择基类为QWidget: image.png

PageSelector类提供了PDF的页数操作,具有的功能有:

  • 向前翻页
  • 向后翻页
  • 当前页数显示与跳转
  • 总页数统计

改造头文件:

#ifndef PAGESELECTOR_H
#define PAGESELECTOR_H

#include <QWidget>

QT_BEGIN_NAMESPACE
class QLabel;
class QLineEdit;
class QPdfDocument;
class QPdfPageNavigation;
class QToolButton;
QT_END_NAMESPACE

class PageSelector : public QWidget
{
    Q_OBJECT
public:
    explicit PageSelector(QWidget *parent = nullptr);               //构造页选择栏

    void setPageNavigation(QPdfPageNavigation *pageNavigation);     //设置pdf导航栏

private slots:
    void onCurrentPageChanged(int page);        //当前页切换
    void pageNumberEdited();                    //页跳转

private:
    QPdfPageNavigation *m_pageNavigation;

    QLineEdit *m_pageNumberEdit;                //当前页数
    QLabel *m_pageCountLabel;                   //总页数
    QToolButton *m_previousPageButton;          //上一页
    QToolButton *m_nextPageButton;              //下一页

};

#endif // PAGESELECTOR_H

源文件中的构造函数和其他函数实现:

#include "pageselector.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPdfPageNavigation>
#include <QToolButton>

PageSelector::PageSelector(QWidget *parent)
    : QWidget(parent)
    , m_pageNavigation(nullptr)
{
    //水平排列
    QHBoxLayout *layout = new QHBoxLayout(this);

    //向上翻页
    m_previousPageButton = new QToolButton(this);
    m_previousPageButton->setText("<");
    m_previousPageButton->setEnabled(false);
    //当前页数
    m_pageNumberEdit = new QLineEdit(this);
    m_pageNumberEdit->setAlignment(Qt::AlignRight);
    //页数统计
    m_pageCountLabel = new QLabel(this);
    m_pageCountLabel->setText("0");
    //向后翻页
    m_nextPageButton = new QToolButton(this);
    m_nextPageButton->setText(">");
    m_nextPageButton->setEnabled(false);
    //向布局中添加组件
    layout->addWidget(m_previousPageButton);
    layout->addWidget(m_pageNumberEdit);
    layout->addWidget(m_pageCountLabel);
    layout->addWidget(m_nextPageButton);
}

void PageSelector::setPageNavigation(QPdfPageNavigation *pageNavigation)
{
    m_pageNavigation = pageNavigation;

    //单击向上翻页按钮,将当前页面更改为上一页
    connect(m_previousPageButton, &QToolButton::clicked, m_pageNavigation, &QPdfPageNavigation::goToPreviousPage);
    //返回当前页之前是否有页,如果有上一页则向上翻页按钮可以使用,否则就禁止向上翻页按钮使用
    connect(m_pageNavigation, &QPdfPageNavigation::canGoToPreviousPageChanged, m_previousPageButton, &QToolButton::setEnabled);

    //当前页码属性与页码输入栏绑定
    connect(m_pageNavigation, &QPdfPageNavigation::currentPageChanged, this, &PageSelector::onCurrentPageChanged);
    //总页数与显示总页数的标签绑定
    connect(m_pageNavigation, &QPdfPageNavigation::pageCountChanged, this, [this](int pageCount){ m_pageCountLabel->setText(QString::fromLatin1("/ %1").arg(pageCount)); });

    //当前页码输入与页码跳转绑定
    connect(m_pageNumberEdit, &QLineEdit::editingFinished, this, &PageSelector::pageNumberEdited);

    //单击向下翻页按钮,将当前页面更改为下一页
    connect(m_nextPageButton, &QToolButton::clicked, m_pageNavigation, &QPdfPageNavigation::goToNextPage);
    //返回当前页之后是否有页,如果有下一页则下上翻页按钮可以使用,否则就禁止向下翻页按钮使用
    connect(m_pageNavigation, &QPdfPageNavigation::canGoToNextPageChanged, m_nextPageButton, &QToolButton::setEnabled);

    //设置当前页码
    onCurrentPageChanged(m_pageNavigation->currentPage());
}

void PageSelector::onCurrentPageChanged(int page)
{
    if (m_pageNavigation->pageCount() == 0)
        m_pageNumberEdit->setText(QString::number(0));
    else
        m_pageNumberEdit->setText(QString::number(page + 1));
}

void PageSelector::pageNumberEdited()
{
    if (!m_pageNavigation)
        return;

    const QString text = m_pageNumberEdit->text();

    //将输入数字字符串转换为int类型
    bool ok = false;
    const int pageNumber = text.toInt(&ok);

    if (!ok)
        onCurrentPageChanged(m_pageNavigation->currentPage());
    else
        m_pageNavigation->setCurrentPage(qBound(0, pageNumber - 1, m_pageNavigation->pageCount() - 1));
}

创建ZoomSelector类

ZoomSelector类创建步骤与PageSelector类的创建步骤基本类似,不同的是ZoomSelector类的基类选择为QComboBox:

image.png

ZoomSelector类提供了PDF页面缩放的操作,具体功能有:

  • 按照最大宽度填充
  • 按照最大页面填充
  • 百分比填充
  • 放大
  • 缩小

改造头文件:

#ifndef ZOOMSELECTOR_H
#define ZOOMSELECTOR_H

#include <QComboBox>
#include <QPdfView>

class ZoomSelector : public QComboBox
{
    Q_OBJECT
public:
    explicit ZoomSelector(QWidget *parent = nullptr);   //构造页面大小选择栏

public slots:
    void setZoomFactor(qreal zoomFactor);               //设置缩放比例

    void reset();                                       //重置页面缩放比例

signals:
    void zoomModeChanged(QPdfView::ZoomMode zoomMode);  //更改缩放模式
    void zoomFactorChanged(qreal zoomFactor);           //更改缩放比例

private slots:
    void onCurrentTextChanged(const QString &text);     //当前缩放比例
};

#endif // ZOOMSELECTOR_H

源文件中的构造函数和其他函数实现:

#include "zoomselector.h"

#include <QLineEdit>

ZoomSelector::ZoomSelector(QWidget *parent)
    : QComboBox(parent)
{
    setEditable(true);

    //添加多种缩放模式
    addItem(QLatin1String("Fit Width"));
    addItem(QLatin1String("Fit Page"));
    addItem(QLatin1String("12%"));
    addItem(QLatin1String("25%"));
    addItem(QLatin1String("33%"));
    addItem(QLatin1String("50%"));
    addItem(QLatin1String("66%"));
    addItem(QLatin1String("75%"));
    addItem(QLatin1String("100%"));
    addItem(QLatin1String("125%"));
    addItem(QLatin1String("150%"));
    addItem(QLatin1String("200%"));
    addItem(QLatin1String("400%"));

    //将缩放选择栏与缩放响应函数绑定
    connect(this, &QComboBox::currentTextChanged,
            this, &ZoomSelector::onCurrentTextChanged);

    //将缩放比例栏输入框与缩放响应函数绑定
    connect(lineEdit(), &QLineEdit::editingFinished,
            this, [this](){onCurrentTextChanged(lineEdit()->text()); });
}

void ZoomSelector::setZoomFactor(qreal zoomFactor)
{
    //以百分比的形式设置缩放比例
    setCurrentText(QString::number(qRound(zoomFactor * 100)) + QLatin1String("%"));
}

void ZoomSelector::reset()
{
    setCurrentIndex(8); // 默认缩放比例为100%
}

void ZoomSelector::onCurrentTextChanged(const QString &text)
{
    if (text == QLatin1String("Fit Width")) {
        emit zoomModeChanged(QPdfView::FitToWidth);
    } else if (text == QLatin1String("Fit Page")) {
        emit zoomModeChanged(QPdfView::FitInView);
    } else {
        qreal factor = 1.0;

        //去掉文字框中的“%”号
        QString withoutPercent(text);
        withoutPercent.remove(QLatin1Char('%'));

        //将文字串变为int类型
        bool ok = false;
        const int zoomLevel = withoutPercent.toInt(&ok);
        if (ok)
            factor = zoomLevel / 100.0;

        emit zoomModeChanged(QPdfView::CustomZoom);
        emit zoomFactorChanged(factor);
    }
}