Python+PyQt5实现自制pdf工具箱

 更新时间:2023年12月11日 08:38:54   作者:mYlEaVeiSmVp  
这篇文章主要为大家详细介绍了Python如何利用PyQt5自制pdf工具箱,可以实现合并拆分和删除指定pdf页面,感兴趣的小伙伴可以跟随小编一起学习一下

pdf工具,之前写的合并工具有点麻烦,使用PyQt5库重写合并拆分和删除指定页面的程序

实现如图:

代码:

import sys
import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget, QFileDialog, QListWidget, QMessageBox, QLineEdit, QHBoxLayout, QInputDialog
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyPDF2 import PdfReader, PdfWriter, PdfMerger
from PyQt5 import QtGui

class CustomListWidget(QListWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

class Worker(QThread):
    finished = pyqtSignal(str)
    error = pyqtSignal(str)
    def __init__(self, pdf_files, range_str=None, save_path=None, operation=None):
        super().__init__()
        self.pdf_files = pdf_files
        self.range_str = range_str
        self.save_path = save_path
        self.operation = operation
    def run(self):
        try:
            if self.operation == 'merge':
                merger = PdfMerger()
                for pdf in self.pdf_files:
                    merger.append(pdf)
                merger.write(self.save_path)
                merger.close()
                self.finished.emit('PDF文件已成功合并。')
            elif self.operation == 'split':
                start_page, end_page = self.parse_range(self.range_str)
                reader = PdfReader(self.pdf_files[zxsq-anti-bbcode-0])
                os.makedirs(self.save_path, exist_ok=True)
                for page in range(start_page, end_page + 1):
                    writer = PdfWriter()
                    writer.add_page(reader.pages)
                    split_save_path = os.path.join(self.save_path, f'Page_{page + 1}.pdf')
                    writer.write(split_save_path)
                self.finished.emit('PDF文件已成功拆分并保存。')
            elif self.operation == 'delete':
                start_page, end_page = self.parse_range(self.range_str)
                reader = PdfReader(self.pdf_files[zxsq-anti-bbcode-0])
                writer = PdfWriter()
                for page_num in range(len(reader.pages)):
                    if not (start_page <= page_num <= end_page):
                        writer.add_page(reader.pages[zxsq-anti-bbcode-page_num])
                writer.write(self.save_path)
                self.finished.emit('指定页面已从PDF中删除。')
        except Exception as e:
            self.error.emit(str(e))
    def parse_range(self, range_str):
        if '-' in range_str:
            start_page, end_page = map(int, range_str.split('-'))
        else:
            start_page = end_page = int(range_str)
        return start_page - 1, end_page - 1  # Convert to 0-based index

class PDFMergerApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.pdf_files = []
    def initUI(self):
        self.setWindowTitle('PDF 工具箱')
        self.setWindowIcon(QtGui.QIcon('111.ico'))
        self.setGeometry(100, 100, 800, 600)
        mainLayout = QVBoxLayout()
        self.addButton = QPushButton('添加 PDF', self)
        self.addButton.clicked.connect(self.addPDF)
        mainLayout.addWidget(self.addButton)
        self.listWidget = CustomListWidget(self)
        mainLayout.addWidget(self.listWidget)
        # 删除按钮的水平布局
        deleteLayout = QHBoxLayout()
        self.removeButton = QPushButton('删除选定', self)
        self.removeButton.clicked.connect(self.removeSelected)
        deleteLayout.addWidget(self.removeButton)
        self.removeAllButton = QPushButton('删除全部', self)
        self.removeAllButton.clicked.connect(self.removeAll)
        deleteLayout.addWidget(self.removeAllButton)
        mainLayout.addLayout(deleteLayout)
        self.mergeButton = QPushButton('合并 PDFs', self)
        self.mergeButton.clicked.connect(self.mergePDFs)
        mainLayout.addWidget(self.mergeButton)
        # 拆分和删除页码的水平布局
        splitDeleteLayout = QHBoxLayout()
        self.splitInput = QLineEdit(self)
        self.splitInput.setPlaceholderText('输入拆分范围,如 1 或 1-4')
        splitDeleteLayout.addWidget(self.splitInput)
        self.splitButton = QPushButton('拆分 PDF', self)
        self.splitButton.clicked.connect(self.splitPDF)
        splitDeleteLayout.addWidget(self.splitButton)
        self.deleteInput = QLineEdit(self)
        self.deleteInput.setPlaceholderText('输入删除页码,如 1 或 1-4')
        splitDeleteLayout.addWidget(self.deleteInput)
        self.deleteButton = QPushButton('删除页面', self)
        self.deleteButton.clicked.connect(self.deletePages)
        splitDeleteLayout.addWidget(self.deleteButton)
        mainLayout.addLayout(splitDeleteLayout)
        container = QWidget()
        container.setLayout(mainLayout)
        self.setCentralWidget(container)
    def addPDF(self):
        files, _ = QFileDialog.getOpenFileNames(self, '打开文件', '', 'PDF files (*.pdf)')
        for file_path in files:
            self.addPDFFile(file_path)
    def addPDFFile(self, file_path):
        if file_path and file_path not in self.pdf_files:
            self.pdf_files.append(file_path)
            self.listWidget.addItem(file_path)
    def removeSelected(self):
        for item in self.listWidget.selectedItems():
            self.pdf_files.remove(item.text())
            self.listWidget.takeItem(self.listWidget.row(item))
    def removeAll(self):
        self.pdf_files.clear()
        self.listWidget.clear()
    def mergePDFs(self):
        save_path, _ = QFileDialog.getSaveFileName(self, '保存文件', '', 'PDF files (*.pdf)')
        if save_path:
            self.thread = Worker(self.pdf_files, save_path=save_path, operation='merge')
            self.thread.finished.connect(self.onFinished)
            self.thread.error.connect(self.onError)
            self.thread.start()
    def splitPDF(self):
        if len(self.pdf_files) != 1:
            QMessageBox.warning(self, "错误", "请只选择一个PDF文件进行拆分。")
            return
        range_str = self.splitInput.text().strip()
        folder_path = self.getFolderName()
        if range_str and folder_path:
            self.thread = Worker(self.pdf_files, range_str=range_str, save_path=folder_path, operation='split')
            self.thread.finished.connect(self.onFinished)
            self.thread.error.connect(self.onError)
            self.thread.start()
    def getFolderName(self):
        folder_path = QFileDialog.getExistingDirectory(self, "选择保存拆分文件的位置")
        if folder_path:
            folder_name, ok = QInputDialog.getText(self, "文件夹名称", "输入文件夹名称:")
            if ok and folder_name:
                full_path = os.path.join(folder_path, folder_name)
                os.makedirs(full_path, exist_ok=True)
                return full_path
        return None
    def deletePages(self):
        if len(self.pdf_files) != 1:
            QMessageBox.warning(self, "错误", "请只选择一个PDF文件进行删除操作。")
            return
        range_str = self.deleteInput.text().strip()
        save_path = QFileDialog.getSaveFileName(self, '保存文件', '', 'PDF files (*.pdf)')[zxsq-anti-bbcode-0]
        if save_path and range_str:
            self.thread = Worker(self.pdf_files, range_str=range_str, save_path=save_path, operation='delete')
            self.thread.finished.connect(self.onFinished)
            self.thread.error.connect(self.onError)
            self.thread.start()
    def onFinished(self, message):
        self.show_message("操作完成", message)
        self.clear_pdf_list()
    def onError(self, error_message):
        self.show_message("操作失败", error_message)
    def show_message(self, title, message):
        QMessageBox.information(self, title, message)
    def clear_pdf_list(self):
        self.pdf_files.clear()
        self.listWidget.clear()
def main():
    app = QApplication(sys.argv)
    ex = PDFMergerApp()
    ex.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

到此这篇关于Python+PyQt5实现自制pdf工具箱的文章就介绍到这了,更多相关Python pdf内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python中最大最小赋值小技巧(分享)

    Python中最大最小赋值小技巧(分享)

    下面小编就为大家分享一篇Python中最大最小赋值小技巧,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • 详解Python的连接符

    详解Python的连接符

    这篇文章主要为大家介绍了Python的连接符,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • Python Pandas知识点之缺失值处理详解

    Python Pandas知识点之缺失值处理详解

    这篇文章主要给大家介绍了关于Pandas知识点之缺失值处理的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • Python中字符串格式化的方法详解

    Python中字符串格式化的方法详解

    众所周知,我们可以使用 print() 方法来输出一个固定内容的字符串,就像是 print("Hello, world!") 一样,但是,在现实中,我们很多时候是需要输出一些内容不断变化,或者内容动态生成的字符串,本文将介绍如何按照需要,在Python中格式化一个字符串
    2023-10-10
  • Python的Flask框架中配置多个子域名的方法讲解

    Python的Flask框架中配置多个子域名的方法讲解

    Fask中可以通过通配符子域的方式来部署多个子域名,这里我们就来作一个Python的Flask框架中配置多个子域名的方法讲解,需要的朋友可以参考下
    2016-06-06
  • Python: glob匹配文件的操作

    Python: glob匹配文件的操作

    这篇文章主要介绍了Python: glob匹配文件的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • python统计中文字符数量的两种方法

    python统计中文字符数量的两种方法

    今天小编就为大家分享一篇python统计中文字符数量的两种方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-01-01
  • Python 使用SMTP发送邮件的代码小结

    Python 使用SMTP发送邮件的代码小结

    python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装,需要的朋友可以参考下
    2016-09-09
  • python的schedule定时任务模块二次封装方法

    python的schedule定时任务模块二次封装方法

    今天小编就为大家分享一篇python的schedule定时任务模块二次封装方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-02-02
  • 浅谈python量化 双均线策略(金叉死叉)

    浅谈python量化 双均线策略(金叉死叉)

    这篇文章主要介绍了浅谈python量化 双均线策略(金叉死叉),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-06-06

最新评论