【QT】 QT开发PDF阅读器

很高兴在雪易的CSDN遇见你 ,给你糖糖

欢迎大家加入雪易社区-CSDN社区云 


前言

本文分享QT开发PDF阅读器技术,希望对各位小伙伴有所帮助!

感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步!

你的点赞就是我的动力(^U^)ノ~YO

结果展示:

我将收获到的:

        1. 如何创建PDFViewer

        2.创建PDFViewer所依赖的QT库

        3.PDFViewer的用处

目录

前言

1.准备PDFViewer所依赖的库

2.创建PDF Viewer

小结:


1.准备PDFViewer所依赖的库

        》使用开发的QT版本:5.15.2

        》存在问题:不能直接添加PDF模块

        》原因:QT5.15.2版本已带有pdf模块,但并未在include中包含,但是在lib和bin目录下能找到相应的.lib和.dll文件。

        》解决方案:

                》下载QT5.15.2源码

                》将“Qt\5.15.2\Src\qtwebengine\include”文件夹下的QtPdf和QtPdfWidgets复制到“Qt\5.15.2\msvc2019_64\include”文件夹下。

                》 将“Qt\5.15.2\Src\qtwebengine\src\pdf\api”文件夹下的.h文件复制到“Qt\5.15.2\msvc2019_64\include\QtPdf”文件夹下。

                》 将“Qt\5.15.2\Src\qtwebengine\src\pdfwidgets”文件夹下的.h文件复制到“Qt\5.15.2\msvc2019_64\include\QtPdfWidgets”文件夹下 

                 》我已将QtPdf整理成单独的依赖库,需要的小伙伴可以联系我下载。

                    也上传CSDN,下载地址:QT开发PDF阅读器,代码简洁易用!资源-CSDN文库 

2.创建PDF Viewer

        》创建UI文件

        》核心为PageSelector(页面选择)和ZoomSelector(缩放)

        》下载地址:QT开发PDF阅读器,代码简洁易用!资源-CSDN文库

        》代码如下:

        PageSelector.h文件

#ifndef PAGESELECTOR_H
#define PAGESELECTOR_H

#include <QWidget>

class QLabel;
class QLineEdit;
class QPdfDocument;
class QPdfPageNavigation;
class QToolButton;

class PageSelector : public QWidget
{
    Q_OBJECT

public:
    explicit PageSelector(QWidget *parent = nullptr);

    void setPageNavigation(QPdfPageNavigation *pageNavigation);

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

        PageSelector.cpp文件

#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();

    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.h文件

#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

        ZoomSelector.cpp文件

#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, static_cast<void(QComboBox::*)(const QString&)>(&QComboBox::currentIndexChanged),
        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('%'));

        bool ok = false;
        const int zoomLevel = withoutPercent.toInt(&ok);
        if (ok)
            factor = zoomLevel / 100.0;

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

小结:

        本文主要分享了开发PDF阅读器所依赖的库,以及开发的过程,谢谢各位小伙伴的关注。

感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步!

你的赞赏是我的最最最最大的动力(^U^)ノ~YO

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/67734.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

matplotlib 笔记 plt.grid

用于添加网格线 主要参数 visible 布尔值&#xff0c;True表示画网格 which表示要显示的刻度线类型&#xff0c;可以是 major&#xff08;主刻度&#xff09;或 minor&#xff08;次刻度&#xff09;&#xff0c;或者同时显示&#xff08;both&#xff09;alpha 透明度 …

培训报名小程序-订阅消息发送

目录 1 创建API2 获取模板参数3 编写自定义代码4 添加订单编号5 发送消息6 发布预览 我们上一篇讲解了小程序如何获取用户订阅消息授权&#xff0c;用户允许我们发送模板消息后&#xff0c;按照模板的参数要求&#xff0c;我们需要传入我们想要发送消息的内容给模板&#xff0c…

Vue实战技巧:从零开始封装全局防抖和节流函数

前言 你是否曾经遇到过用户频繁点击按钮或滚动页面导致反应迟钝的问题&#xff1f;这是因为事件被连续触发&#xff0c;导致性能下降。在本文中&#xff0c;我将为大家介绍 vue 中的防抖和节流策略&#xff0c;并展示如何封装全局的防抖节流函数&#xff0c;以避免频繁触发事件…

米尔瑞萨RZ/G2L开发板-01 开箱+环境搭建+交叉编译FFMPEG

标题有点长哈&#xff0c;首先要感谢米尔电子提供的开发板&#xff0c;异构的板子说实话还真的是最近才开始接触的&#xff0c;在我提交申请后&#xff0c;很快就收到板子了&#xff0c;而且还是顺丰给发来的&#xff0c;其实我估计很多人就是为了骗板子&#xff0c;因为米尔的…

LeetCode150道面试经典题-移除元素(简单)

目录 1.题目 2.解题思路 3.解题代码 1.题目 移除元素 给你一个数组 nums 和一个值 val&#xff0c;你需要原地移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并原地修改输入数组。 元素…

Idea中侧面栏不见了,如何设置?

一、打开idea点击File然后点击Setting 二、点击Appearance,然后划到最下面&#xff0c;勾选Show tool windows bars和Side-by-side layout on the left 三、侧面栏目正常显示

Chatgpt AI newbing作画,文字生成图 BingImageCreator 二次开发,对接wxbot

开源项目 https://github.com/acheong08/BingImageCreator 获取cookie信息 cookieStore.get("_U").then(result > console.log(result.value)) pip3 install --upgrade BingImageCreator import os import BingImageCreatoros.environ["http_proxy"]…

微信小程序的项目解构

视频链接 黑马程序员前端微信小程序开发教程&#xff0c;微信小程序从基础到发布全流程_企业级商城实战(含uni-app项目多端部署)_哔哩哔哩_bilibili 接口文档 https://www.escook.cn/docs-uni-shop/mds/1.start.html 1&#xff1a;微信小程序宿主环境 1&#xff1a;常见的宿…

无涯教程-Perl - index函数

描述 此函数返回STR中第一次出现的SUBSTR的位置,该位置从开头(从零开始)开始,或者从POSITION(如果指定)开始。 语法 以下是此函数的简单语法- index STR, SUBSTR, POSITIONindex STR, SUBSTR返回值 失败时此函数返回-1,否则返回匹配字符串的位置(第一个字符从零开始)。 例…

【从0开始离线数仓项目】——数据仓库的环境搭建(1)

目录 一、服务器环境准备 1.2 编写集群分发脚本xsync 1.3 SSH无密登录配置 1.4 JDK准备 1.5 环境变量配置说明 二、集群所有进程查看脚本 三、Zookeeper安装 3.1 分布式安装部署 3.2 ZK集群启动停止脚本 3.3 客户端命令行操作 一、服务器环境准备 CentOS 7 怎么从命…

【uniapp】一文读懂app端安装包升级

一、前言 首先&#xff0c;在app端开发上线的过程中&#xff0c;会面临一个问题&#xff0c;就是关于app端的版本升级的问题。如果不做相关处理来引导用户的话&#xff0c;那么app就会出现版本没有更新出现的各种问题&#xff0c;我们常见的有在线升级和去指定地址下载安装两种…

web-xss

一、简介 XSS 又称CSS(Cross Site Scripting)或跨站脚本攻击&#xff0c;攻击者在网页中插入由JavaScript编写的恶意代码&#xff0c;当用户浏览被嵌入恶意代码的网页时&#xff0c;恶意代码将会在用户的浏览器上执行。 二、xss的攻击方式 Dom&#xff1a;这是一种将任意 Jav…

hive on tez资源控制

sql insert overwrite table dwintdata.dw_f_da_enterprise2 select * from dwintdata.dw_f_da_enterprise; hdfs文件大小数量展示 注意这里文件数有17个 共计321M 最后是划分为了21个task 为什么会有21个task&#xff1f;不是128M 64M 或者说我这里小于128 每个文件一个map…

【web逆向】全报文加密流量的去加密测试方案

aHR0cHM6Ly90ZGx6LmNjYi5jb20vIy9sb2dpbg 国密混合 WEB JS逆向篇 先看报文&#xff1a;请求和响应都是全加密&#xff0c;这种情况就不像参数加密可以方便全文搜索定位加密代码&#xff0c;但因为前端必须解密响应的密文&#xff0c;因此万能的方法就是搜索拦截器&#xff0c…

Springboot中创建拦截器

目录 目的 实现过程 1、创建拦截器 2、注册拦截器 完整代码 目的 在Springboot项目中创建拦截器&#xff0c;在进入Controller层之前拦截请求&#xff0c;可对拦截到的请求内容做响应处理&#xff0c;如&#xff1a;校验请求参数、验证证书等操作&#xff1b; 实现过程 1、创…

基于Java+SpringBoot+Vue的数码论坛系统设计与实现(源码+LW+部署文档等)

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

用于3D MRI和CT扫描的深度学习模型总结

医学成像数据与其他我们日常图像的最大区别之一是它们很多都是3D的&#xff0c;比如在处理DICOM系列数据时尤其如此。DICOM图像由很多的2D切片组成了一个扫描或身体的特定部分。 那么如何为这类数据构建深度学习解决方案呢?本文中将介绍6种神经网络架构&#xff0c;可以使用它…

数据结构:各种结构函数参数辨析

&#xff08;一&#xff09;顺序表 1&#xff09;结构 typedef int SLDateType;typedef struct SeqList {SLDateType* data;int size;int capacity; }SeqList;SeqList ps { 0 }; 2&#xff09;函数参数 // 对数据的管理:增删查改 void SeqListInit(SeqList* ps); void Seq…

webpack基础知识六:说说webpack的热更新是如何做到的?原理是什么?

一、是什么 HMR全称 Hot Module Replacement&#xff0c;可以理解为模块热替换&#xff0c;指在应用程序运行过程中&#xff0c;替换、添加、删除模块&#xff0c;而无需重新刷新整个应用 例如&#xff0c;我们在应用运行过程中修改了某个模块&#xff0c;通过自动刷新会导致…

Android Glide MemorySizeCalculator计算值,Kotlin

Android Glide MemorySizeCalculator计算值,Kotlin for (i in 100..1000 step 50) {val calculator MemorySizeCalculator.Builder(this).setMemoryCacheScreens(i.toFloat()).setBitmapPoolScreens(i.toFloat()).setMaxSizeMultiplier(0.8f).setLowMemoryMaxSizeMultiplier(0…