Qt下使用QtPdfium处理PDF文档

news2025/1/12 8:54:07

文章目录

  • 前言
  • 一、使用QPdfDocument
  • 二、使用QtPdfium
  • 三、示例完整代码
  • 总结


前言

在我之前的文章中,有提到如何生成PDF,这个可以查看文末参考文章。如果要实现在Qt下进行PDF文档的处理(读取显示),可以使用自带的PDF库以及集成一些第三方库,在这里我使用了QtPdfium(基于Pdfium的Qt封装版本)来处理PDF文档,详细内容见下文,大家可以参考学习,如有错误之处,欢迎大家批评指正。

项目效果
请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、使用QPdfDocument

在Qt中,可以使用QPdfDocument类来处理PDF文档,我目前使用的5.14.2版本,结果发现找不到这个类,查询相关资料应该在5.15版本后才有的。用这个类进行PDF的处理也是比较好用的,由于我目前版本不支持,所有就没使用这种方法,如何使用可见这篇文章:QT自带PDF库的使用

二、使用QtPdfium

QtPdfium是基于Pdfium的Qt封装版本,如果想要根据你当前使用的编译套件集成库,需要先对其进行相应版本的编译,对于QtPdfium的编译,可以跟着这篇文章中的步骤:qtpdfium的编译及读取pdf文件和一些简单操作
这里我使用的是MSVC_64位进行编译的,然后将生成的lib以及头文件打包放在项目同级目录下,然后在pro文件中添加下列代码(可以直接像我这样添加,也可以按照上面参考步骤中添加库进行操作)

INCLUDEPATH += $$PWD/qtpdfium/include
DEPENDPATH += $$PWD/qtpdfium/include
LIBS += -L$$PWD/qtpdfium/lib/ -lQt5Pdfium

三、示例完整代码

我的示例中实现了打开PDF文档,可以进行翻页显示,跳转到指定页显示,界面缩放显示以及将当前页显示的内容保存为jpg/png图像,具体实现见下面这些代码:
1.PDFTest.pro


2.mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileDialog>
#include <QDesktopServices>
#include <QTime>
#include <QImage>
#include <QPixmap>
#include <QWheelEvent>
#include <QDebug>

#include "qpdfium.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void initWidget();
    void showPdfData(int curPage);
    void updateScaledPixmap();

protected:
    void wheelEvent(QWheelEvent *event) override;

private slots:
    void on_pb_open_clicked();
    void on_pb_previous_clicked();
    void on_pb_next_clicked();
    void on_pb_saveImage_clicked();
    void on_pb_viewImage_clicked();

    void on_le_assignPage_editingFinished();


private:
    Ui::MainWindow *ui;

    int m_curPage;        //当前页
    int m_totalPage;      //总页数
    double m_zoomScale;   //缩放比例
    bool m_validFlag;     //打开pdf是否有效
    QString m_saveImagePath;   //图像保存路径
    QPixmap m_showPixmap;      //界面显示图像

    QPdfium *m_pdfium;   //QPdfium对象

};
#endif // MAINWINDOW_H

3.mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->initWidget();
}

MainWindow::~MainWindow()
{
    delete ui;
}

//初始化界面
void MainWindow::initWidget()
{
    //初始化变量
    m_curPage = 0;
    m_totalPage = 0;
    m_zoomScale = 1.0;
    m_validFlag = false;
    m_saveImagePath = "";
    m_showPixmap = QPixmap();

    //实例化QPdfium对象
    m_pdfium = new QPdfium();

    //exe运行目录下创建保存图像的文件夹
    QString exePath = QCoreApplication::applicationDirPath();
    m_saveImagePath = exePath + "/保存图像/";
    QDir dstDir(m_saveImagePath);
    if(!dstDir.exists())
    {
        if(!dstDir.mkpath(m_saveImagePath))
        {
            qDebug()<<m_saveImagePath<<"文件夹创建失败!";
        }
    }
}

//显示指定页内容
void MainWindow::showPdfData(int curPage)
{
    QPdfiumPage pdfiumPage = m_pdfium->page(curPage);
    QImage image = pdfiumPage.image();
    m_showPixmap = QPixmap::fromImage(image).scaled(ui->lb_image->size(),
                   Qt::IgnoreAspectRatio,Qt::SmoothTransformation);   //IgnoreAspectRatio:填满   KeepAspectRatio:保持比例
    ui->lb_image->setPixmap(m_showPixmap);
    QString text = pdfiumPage.text();
    qDebug()<<"第"<<curPage+1<<"PDF文本内容:"<<text;

    //刷新当前页
    ui->lb_curPage->setText(QString::number(curPage+1));
    ui->le_assignPage->setText(QString::number(curPage+1));
}

//鼠标滚轮事件
void MainWindow::wheelEvent(QWheelEvent *event)
{
    if(!m_validFlag)
    {
        return;
    }

    //根据鼠标滚轮的方向来缩放图像
    const QPoint numDegrees = event->angleDelta() / 8;
    const int numSteps = numDegrees.y() / 15;

    if(numSteps != 0)
    {
        //更新缩放比例
        if(numSteps > 0)
        {
            //放大
            m_zoomScale *= 1.1;
        }
        else
        {
            //缩小,但要确保缩放比例不会小于某个最小值(比如0.1)
            m_zoomScale /= 1.1;
            m_zoomScale = qMax(m_zoomScale,0.1);
        }

        //更新缩放后的图像并显示
        updateScaledPixmap();
    }
}

//更新缩放图像
void MainWindow::updateScaledPixmap()
{
    //计算缩放后的尺寸
    QSize scaledSize = m_showPixmap.size() * m_zoomScale;

    //缩放图像
    QPixmap scaledPixmap = m_showPixmap.scaled(scaledSize,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);

    //更新QLabel的Pixmap
    ui->lb_image->setPixmap(scaledPixmap);
}

//打开文件
void MainWindow::on_pb_open_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,"打开PDF文件","D:/PDF/","PDF Files (*.pdf)");
    if(!fileName.isEmpty())
    {
        m_pdfium->loadFile(fileName);
        m_validFlag = m_pdfium->isValid();
        if(m_validFlag)
        {
            m_totalPage = m_pdfium->pageCount();
            ui->lb_totalPage->setText(QString::number(m_totalPage));
            qDebug()<<"读取pdf文件页数为:"<<m_totalPage;
            if(m_totalPage > 0)
            {
                m_curPage = 0;
                showPdfData(m_curPage);
            }
        }
        else
        {
            ui->lb_curPage->setText("0");
            ui->lb_totalPage->setText("0");
            ui->lb_image->setText("打开失败!");
        }
    }
    else
    {
        m_validFlag = false;
        ui->lb_curPage->setText("0");
        ui->lb_totalPage->setText("0");
        ui->lb_image->setText("打开失败!");
    }
}

//保存图像
void MainWindow::on_pb_saveImage_clicked()
{
    if(m_validFlag)
    {
        //以当前页数+时间组装名称
        QString curPage = ui->lb_curPage->text();
        QString curTime = QTime::currentTime().toString("_hhmmss");
        QString imageName = m_saveImagePath + curPage + curTime;

        //第一种方式:保存QPixmap到文件,这里保存为jpg格式
        qDebug()<<"保存图像名:"<<imageName + ".jpg";
        if(ui->lb_image->pixmap()->save(imageName + ".jpg"))
        {
            qDebug()<<"保存成功!";
        }
        else
        {
            qDebug()<<"保存失败!";
        }

        //第二种方式:保存QImage到文件,这里保存为png格式
        qDebug()<<"保存图像名:"<<imageName + ".png";
        QPdfiumPage pdfiumPage = m_pdfium->page(m_curPage);
        QImage image = pdfiumPage.image();
        if(image.save(imageName + ".png"))
        {
            qDebug()<<"保存成功!";
        }
        else
        {
            qDebug()<<"保存失败!";
        }
    }
}

//查看图像
void MainWindow::on_pb_viewImage_clicked()
{
    if(!QDesktopServices::openUrl(QUrl::fromLocalFile(m_saveImagePath)))
    {
        qDebug()<<"存图路径打开失败!";
    }
}

//上一页
void MainWindow::on_pb_previous_clicked()
{
    if(m_validFlag)
    {
        if(m_curPage > 0)
        {
            m_curPage--;
        }
        showPdfData(m_curPage);
    }
}

//下一页
void MainWindow::on_pb_next_clicked()
{
    if(m_validFlag)
    {
        if(m_curPage < m_totalPage-1)
        {
            m_curPage++;
        }
        showPdfData(m_curPage);
    }
}

//跳转到指定页
void MainWindow::on_le_assignPage_editingFinished()
{
    if(m_validFlag)
    {
        int curPage = ui->le_assignPage->text().toInt() - 1;
        if(curPage < 0)
        {
            m_curPage = 0;
        }
        else if(curPage > m_totalPage-1)
        {
            m_curPage = m_totalPage-1;
        }
        else
        {
            m_curPage = curPage;
        }
        showPdfData(m_curPage);
    }
}

4.mainwindow.ui
请添加图片描述


总结

通过本文示例可以看到使用这个QtPdfium进行PDF的读取也是很简单的,显示在界面上其实就是QImage的应用。但是我在测试过程中,发现无法读取中文路径的PDF,这个问题呢我有尝试过修改编码等来进行解决,还是没有成功,看看大家有没有解决这个问题的方法呢,等待大佬的赐教,多谢!


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

参考文章:
QT自带PDF库的使用
qt 使用qtpdfium实现读取pdf文件
qtpdfium的编译及读取pdf文件和一些简单操作
Qt学习:文本图片自定义拖放操作及界面打印输出PDF文件

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity(2022.3.38LTS) - 基础概念

目录 一. 场景 二. 游戏对象 三. 组件 四. 标签 五. 静态游戏对象 六. 保存 一. 场景 Unity 场景是游戏或应用开发中的一个重要概念。 Unity 场景的组成元素&#xff1a; 它通常包含了各种游戏对象&#xff0c;比如 3D 模型、灯光、摄像机、脚本组件、音频源等等。 作用…

串列翼无人机技术详解

串列翼无人机作为一种特殊布局的飞行器&#xff0c;其概念可追溯至早期航空探索时期。随着航空技术的不断进步&#xff0c;尤其是复合材料、先进控制算法及动力系统的革新&#xff0c;串列翼无人机逐渐从理论走向实践。这一设计初衷在于通过前后两组机翼的巧妙布局&#xff0c;…

Redis Cluster集群

redis-cluster集群 Redis Cluster是Redis官方提供的分布式解决方案。当遇到内存、并发、流量等瓶颈时&#xff0c;就可以采用Cluster架构达到负载均衡目的。 1.Redis单实例主要有单点故障&#xff0c;容量有限&#xff0c;流量压力上限的问题。 Redis单点故障&#xff0c;可以…

全开源智慧停车场微信小程序源码/智能停车系统源码/停车自助缴费系统/停车场管理收费+物业管理+物联网+自助缴费功能

源码简介&#xff1a; 智慧停车场微信小程序源码&#xff0c;全开源智能停车系统源码&#xff0c;停车自助缴费系统&#xff0c;具有停车场管理、停车收费、物业管理、物联网、自助缴费等多种功能。 这是一个全开源的智能停车系统&#xff0c;功能强大。它不仅能帮你管理停车…

如何平衡冷数据(历史库)的成本与性能?| OceanBase应用实践

随着数据量的迅猛增长&#xff0c;企业和组织在数据库管理方面遭遇的挑战愈发凸显。数据库性能逐渐下滑、存储成本节节攀升&#xff0c;以及数据运维复杂性的增加&#xff0c;这些挑战使得DBA和开发者在数据管理上面临更大的压力。 为了应对这些挑战&#xff0c;对数据生命周期…

音频去噪:使用Python和FFT增强音质

根据定义,声音去噪是从音频信号中去除不需要的噪音或干扰,以提高其质量和清晰度的过程。这涉及识别和隔离噪音成分(通常以不规则或高频元素为特征),并将其过滤掉,同时保持原始声音的完整性。 声音去噪目标是改善聆听体验以及音频分析和处理的准确性。过滤掉噪音对于高保真音频…

SQL每日一练-0814

今日SQL题难度&#xff1a;★☆☆☆☆☆☆☆☆☆ 1、题目要求 找出每个部门中薪资最高的员工显示部门ID、部门名称、员工ID、员工姓名以及对应的薪资 2、表和虚拟数据 现有两个表&#xff1a;Employees 和 Departments&#xff0c;记录了员工和部门信息。 CREATE TA…

MySQL-进阶篇-索引

文章目录 1. 准备工作2. 索引概述2.1 什么是索引2.2 索引的优缺点 3. 索引的结构3.1 索引结构介绍3.2 二叉树3.3 BTree3.4 BTree3.5 MySQL 中的 BTree3.6 Hash3.7 思考题&#xff1a;为什么 InnoDB 存储引擎选择使用 BTree 索引结构 4. 索引的分类5. 索引的语法5.1 创建索引5.2…

html+css+js网页制作苹果助手pc1个页面(带js)

htmlcssjs网页制作苹果助手pc1个页面&#xff08;带js&#xff09; 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#x…

解决方案上新了丨趋动科技推出基于银河麒麟操作系统的异构算力池化解决方案

趋动科技携手麒麟软件打造基于银河麒麟操作系统的异构算力池化解决方案&#xff0c;共同探索AI领域新场景。 人工智能技术作为数字经济发展的重要推手&#xff0c;在各行业业务场景中落地需要大量AI算力资源的有效保障。在IT基础设施普遍云化的今天&#xff0c;AI算力一方面需…

【ai】Easy-RAG 不行啊,RAGFlow官方demo行

提取工程:graph-demo-ui.py 没有index.html 过不了。这俩可能是一样的 faiss db 看起来一直报错,txt 输入也不行。chroma 的问题是向量化ok,但是和大模型结合不行。easy-rag代码真不多 chroma db 下的操作 向量化竟然也成功了 问问题不行啊 /home/zhangb

Python 之Web应用开发(Flask框架)

一 Python 简介 1.1 Python是继C&#xff0c;java&#xff0c;C#等编程语言之后又一种面向对象的高级语言&#xff0c;凭借着简单的语法和和丰富的库&#xff0c;2015年开始迅速发展&#xff0c;到今天已成为排行前三的最受欢迎榜。 1.2 Python 应用领域非常广泛&#xff0c;…

华为的流程管理

华为建设流程体系始于2000年&#xff0c;那时华为公司面临着快速扩张和全球化发展的挑战&#xff0c;意识到传统的管理模式已经无法满足业务发展的需求。为了提高公司的管理效率和竞争优势&#xff0c;华为决定启动流程体系的建设。在建设过程中&#xff0c;华为借鉴了业界最佳…

SecureCRT for Mac/Win:安全高效的专业终端SSH工具软件

SecureCRT for Mac/Win是一款功能强大且安全可靠的专业终端SSH工具软件&#xff0c;专为网络管理人员、系统管理员和开发人员设计&#xff0c;旨在提供高效、安全的远程访问和管理解决方案。这款软件以其卓越的性能和丰富的功能&#xff0c;赢得了广泛的用户好评和信赖。 核心…

【Python机器学习】Apriori算法——使用APriori算法来发现频繁集

关联分析的目标包括两项&#xff1a;发现频繁项集和发现关联规则。首先需要找到频繁项集&#xff0c;然后才能获得关联规则。 APriori算法时发现频繁项集的一种方法。APriori算法的两个输入参数是最小支持度和数据集&#xff0c;算法首先会生成所有单个物品的项集列表&#xf…

【源码】Sharding-JDBC源码分析之Yaml分片配置原理(二)

Sharding-JDBC系列 1、Sharding-JDBC分库分表的基本使用 2、Sharding-JDBC分库分表之SpringBoot分片策略 3、Sharding-JDBC分库分表之SpringBoot主从配置 4、SpringBoot集成Sharding-JDBC-5.3.0分库分表 5、SpringBoot集成Sharding-JDBC-5.3.0实现按月动态建表分表 6、【…

奥运奖牌窥视

1 前言 2024巴黎奥运会已经闭幕了&#xff0c;中国队创纪录地获得了海外举办的奥运会的最佳成绩&#xff0c;我们来个管中窥豹&#xff0c;看看中国队从哪些项目中取得了奖牌。 2 奖牌组成 游泳真是大项&#xff0c;小项数量众多&#xff0c;比如个人自由泳就有100m、200m、4…

经纬恒润亮相第四届焉知汽车年会,功能安全赋能域控

8月初&#xff0c;第四届焉知汽车年会在上海举行。此次年会围绕当下智能电动汽车的热点和焦点&#xff0c;聚焦于智能汽车场景应用、车载通信、激光雷达、智能座舱、功能安全、电驱动系统等多个领域&#xff0c;汇聚了来自OEM、科技公司、零部件供应商、测试认证机构、政府院校…

顾客账单管理和台账-SAAS 本地化及未来之窗行业应用跨平台架构

一、客户账单对客户和企业的帮助 为您的企业客户打造便捷新体验&#xff01;现在&#xff0c;企业客户做账消费后&#xff0c;可自行下载账单。这一创新举措不仅大大减少了公司售后的压力&#xff0c;更能助力企业客户提升办公效率。想象一下&#xff0c;无需繁琐的沟通与等待…

论文阅读:一种基于凸规划的高效有向最密子图发现方法 | SIGMOD 2022

论文概述 这篇论文的主题是研究如何在有向图中找到密度最高的子图&#xff0c;这个问题被称为有向最密子图&#xff08;Directed Densest Subgraph, DDS&#xff09;问题。该问题在许多应用中非常重要&#xff0c;如社交网络分析、社区发现、假粉丝检测等。论文提出了一种基于…