Python 创建一个能够筛选文件的PDF合并工具

embedded/2025/3/1 7:43:15/

合并多个 PDF 文件。这款 PDF 合并工具允许用户浏览文件夹、选择 PDF 文件,并将其合并为一个新的 PDF 文件。我们将详细分析代码结构和如何一步步实现每个功能。
C:\pythoncode\new\PDFFileInFolderMergeToNewPDFFile.py

全部代码

python">import os
import wx
import PyPDF2class PDFMergerFrame(wx.Frame):def __init__(self, parent, title):super(PDFMergerFrame, self).__init__(parent, title=title, size=(900, 600))# Create main panelself.panel = wx.Panel(self)# Create toolbarself.toolbar = self.CreateToolBar()# Add toolbar buttonsbrowse_tool = self.toolbar.AddTool(wx.ID_ANY, "浏览", wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN), "浏览文件夹")merge_tool = self.toolbar.AddTool(wx.ID_ANY, "合成", wx.ArtProvider.GetBitmap(wx.ART_NEW), "合成PDF文件")self.toolbar.Realize()# Bind toolbar eventsself.Bind(wx.EVT_TOOL, self.on_browse, browse_tool)self.Bind(wx.EVT_TOOL, self.on_merge, merge_tool)# Create main sizermain_sizer = wx.BoxSizer(wx.HORIZONTAL)# Create left panel for foldersleft_panel = wx.Panel(self.panel)left_sizer = wx.BoxSizer(wx.VERTICAL)folder_label = wx.StaticText(left_panel, label="文件夹:")self.folder_listbox = wx.ListBox(left_panel, size=(200, -1), style=wx.LB_SINGLE)left_sizer.Add(folder_label, 0, wx.ALL, 5)left_sizer.Add(self.folder_listbox, 1, wx.EXPAND | wx.ALL, 5)left_panel.SetSizer(left_sizer)# Create middle panel for filesmiddle_panel = wx.Panel(self.panel)middle_sizer = wx.BoxSizer(wx.VERTICAL)file_label = wx.StaticText(middle_panel, label="子文件:")self.file_listbox = wx.ListBox(middle_panel, size=(200, -1), style=wx.LB_SINGLE)middle_sizer.Add(file_label, 0, wx.ALL, 5)middle_sizer.Add(self.file_listbox, 1, wx.EXPAND | wx.ALL, 5)middle_panel.SetSizer(middle_sizer)# Create button panelbutton_panel = wx.Panel(self.panel)button_sizer = wx.BoxSizer(wx.VERTICAL)add_button = wx.Button(button_panel, label=">")remove_button = wx.Button(button_panel, label="<")button_sizer.Add(add_button, 0, wx.ALL, 5)button_sizer.Add(remove_button, 0, wx.ALL, 5)button_panel.SetSizer(button_sizer)# Create right panel for selected filesright_panel = wx.Panel(self.panel)right_sizer = wx.BoxSizer(wx.VERTICAL)selected_label = wx.StaticText(right_panel, label="已选文件:")self.selected_listbox = wx.ListBox(right_panel, size=(200, -1), style=wx.LB_SINGLE)right_sizer.Add(selected_label, 0, wx.ALL, 5)right_sizer.Add(self.selected_listbox, 1, wx.EXPAND | wx.ALL, 5)right_panel.SetSizer(right_sizer)# Add panels to main sizermain_sizer.Add(left_panel, 1, wx.EXPAND | wx.ALL, 5)main_sizer.Add(middle_panel, 1, wx.EXPAND | wx.ALL, 5)main_sizer.Add(button_panel, 0, wx.EXPAND | wx.ALL, 5)main_sizer.Add(right_panel, 1, wx.EXPAND | wx.ALL, 5)# Set main sizerself.panel.SetSizerAndFit(main_sizer)#         # Set main sizer# self.panel.SetSizerAndFit(main_sizer)# Bind eventsself.folder_listbox.Bind(wx.EVT_LISTBOX, self.on_folder_select)add_button.Bind(wx.EVT_BUTTON, self.on_add_file)remove_button.Bind(wx.EVT_BUTTON, self.on_remove_file)# Initialize variablesself.root_path = ""self.folders_with_files = []# Center and show frameself.Centre()self.Show()def on_browse(self, event):"""Handle browse button click"""dlg = wx.DirDialog(self, "选择文件夹", style=wx.DD_DEFAULT_STYLE)if dlg.ShowModal() == wx.ID_OK:self.root_path = dlg.GetPath()self.scan_folders()dlg.Destroy()def scan_folders(self):"""Scan folders and list those with PDF files"""if not self.root_path:returnself.folders_with_files = []self.folder_listbox.Clear()for root, dirs, files in os.walk(self.root_path):has_pdf = Falsefor file in files:if file.lower().endswith('.pdf'):has_pdf = Truebreakif has_pdf:self.folders_with_files.append(root)folder_name = os.path.basename(root) or rootself.folder_listbox.Append(folder_name)def on_folder_select(self, event):"""Handle folder selection"""selected_index = self.folder_listbox.GetSelection()if selected_index == wx.NOT_FOUND:returnselected_folder = self.folders_with_files[selected_index]self.file_listbox.Clear()for file in os.listdir(selected_folder):if file.lower().endswith('.pdf'):self.file_listbox.Append(file)def on_add_file(self, event):"""Add selected file to the list of files to merge"""selected_file_index = self.file_listbox.GetSelection()selected_folder_index = self.folder_listbox.GetSelection()if selected_file_index == wx.NOT_FOUND or selected_folder_index == wx.NOT_FOUND:returnselected_file = self.file_listbox.GetString(selected_file_index)selected_folder = self.folders_with_files[selected_folder_index]full_path = os.path.join(selected_folder, selected_file)# Check if already in the listfor i in range(self.selected_listbox.GetCount()):if self.selected_listbox.GetClientData(i) == full_path:returnself.selected_listbox.Append(selected_file, full_path)def on_remove_file(self, event):"""Remove selected file from the list of files to merge"""selected_index = self.selected_listbox.GetSelection()if selected_index != wx.NOT_FOUND:self.selected_listbox.Delete(selected_index)def on_merge(self, event):"""Merge selected PDF files"""if self.selected_listbox.GetCount() == 0:wx.MessageBox("请选择至少一个PDF文件", "警告", wx.OK | wx.ICON_WARNING)return# Ask for output filewith wx.FileDialog(self, "保存合并的PDF", wildcard="PDF files (*.pdf)|*.pdf",style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog:if fileDialog.ShowModal() == wx.ID_CANCEL:returnoutput_path = fileDialog.GetPath()try:merger = PyPDF2.PdfMerger()# Add all selected filesfor i in range(self.selected_listbox.GetCount()):file_path = self.selected_listbox.GetClientData(i)merger.append(file_path)# Write to output filemerger.write(output_path)merger.close()wx.MessageBox(f"PDF文件已成功合并为: {output_path}", "成功", wx.OK | wx.ICON_INFORMATION)except Exception as e:wx.MessageBox(f"合并PDF时出错: {str(e)}", "错误", wx.OK | wx.ICON_ERROR)class PDFMergerApp(wx.App):def OnInit(self):frame = PDFMergerFrame(None, "PDF合并工具")self.SetTopWindow(frame)return Trueif __name__ == "__main__":app = PDFMergerApp()app.MainLoop()
背景

wxPython 是一个基于 wxWidgets 的 Python GUI 库,它提供了创建跨平台桌面应用程序的强大工具。PyPDF2 则是一个 Python 库,用于处理 PDF 文件的操作,如合并、拆分、提取文本等。

本示例程序结合了 wxPython 用于构建图形界面和 PyPDF2 用于处理 PDF 合并的功能。

主要功能
  1. 浏览文件夹:用户可以选择一个文件夹,程序会扫描该文件夹下所有的 PDF 文件。
  2. 选择文件:用户可以从文件夹中选择需要合并的 PDF 文件。
  3. 合并文件:用户选择多个 PDF 文件后,程序会将其合并成一个新的 PDF 文件。

接下来,让我们详细分析代码。

代码解析

1. 初始化 wx.Frame 窗口
python">class PDFMergerFrame(wx.Frame):def __init__(self, parent, title):super(PDFMergerFrame, self).__init__(parent, title=title, size=(900, 600))

我们创建了一个继承自 wx.Frame 的类 PDFMergerFrame,这是应用程序的主窗口。窗口的大小为 900x600

2. 创建工具栏
python"># Create toolbar
self.toolbar = self.CreateToolBar()# Add toolbar buttons
browse_tool = self.toolbar.AddTool(wx.ID_ANY, "浏览", wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN), "浏览文件夹")
merge_tool = self.toolbar.AddTool(wx.ID_ANY, "合成", wx.ArtProvider.GetBitmap(wx.ART_NEW), "合成PDF文件")
self.toolbar.Realize()

在窗口中添加了一个工具栏,并且为工具栏添加了两个按钮:

  • 浏览:用来选择文件夹,浏览文件夹并列出包含 PDF 文件的文件夹。
  • 合成:用来合并用户选择的 PDF 文件。

按钮的图标通过 wx.ArtProvider.GetBitmap 方法加载。

3. 创建布局和界面控件

我们使用 wx.BoxSizer 创建了主界面布局,并将不同的控件添加到面板中。

python"># Create main sizer
main_sizer = wx.BoxSizer(wx.HORIZONTAL)

main_sizer 是一个水平的 BoxSizer,用于将控件横向排列。接下来,我们定义了四个面板,分别用于显示:

  • 文件夹选择:显示文件夹列表。
  • 文件选择:显示当前文件夹中的 PDF 文件。
  • 按钮面板:显示添加和移除文件的按钮。
  • 已选文件:显示用户选择的文件列表。

每个面板使用 wx.Panel 创建,并且通过 wx.ListBox 控件展示文件夹或文件列表。

4. 文件夹扫描功能
python">def scan_folders(self):"""Scan folders and list those with PDF files"""if not self.root_path:returnself.folders_with_files = []self.folder_listbox.Clear()for root, dirs, files in os.walk(self.root_path):has_pdf = Falsefor file in files:if file.lower().endswith('.pdf'):has_pdf = Truebreakif has_pdf:self.folders_with_files.append(root)folder_name = os.path.basename(root) or rootself.folder_listbox.Append(folder_name)

scan_folders 函数扫描用户选择的文件夹并列出其中包含 PDF 文件的子文件夹。使用 os.walk 递归遍历文件夹,并筛选出后缀为 .pdf 的文件。如果文件夹中包含 PDF 文件,则将文件夹添加到 folder_listbox

5. 选择文件夹后的操作
python">def on_folder_select(self, event):"""Handle folder selection"""selected_index = self.folder_listbox.GetSelection()if selected_index == wx.NOT_FOUND:returnselected_folder = self.folders_with_files[selected_index]self.file_listbox.Clear()for file in os.listdir(selected_folder):if file.lower().endswith('.pdf'):self.file_listbox.Append(file)

用户在 folder_listbox 中选择一个文件夹后,on_folder_select 方法会被触发。此时,程序会列出该文件夹中的所有 PDF 文件,并显示在 file_listbox 中供用户选择。

6. 添加和移除文件
python">def on_add_file(self, event):"""Add selected file to the list of files to merge"""selected_file_index = self.file_listbox.GetSelection()selected_folder_index = self.folder_listbox.GetSelection()if selected_file_index == wx.NOT_FOUND or selected_folder_index == wx.NOT_FOUND:returnselected_file = self.file_listbox.GetString(selected_file_index)selected_folder = self.folders_with_files[selected_folder_index]full_path = os.path.join(selected_folder, selected_file)# Check if already in the listfor i in range(self.selected_listbox.GetCount()):if self.selected_listbox.GetClientData(i) == full_path:returnself.selected_listbox.Append(selected_file, full_path)

当用户选择文件并点击 > 按钮时,选中的文件将被添加到 selected_listbox 中。在添加之前,程序会检查该文件是否已经在列表中,防止重复添加。

移除文件的操作也是类似的,用户可以通过 < 按钮从 selected_listbox 中删除已选文件。

7. 合并PDF文件
python">def on_merge(self, event):"""Merge selected PDF files"""if self.selected_listbox.GetCount() == 0:wx.MessageBox("请选择至少一个PDF文件", "警告", wx.OK | wx.ICON_WARNING)return# Ask for output filewith wx.FileDialog(self, "保存合并的PDF", wildcard="PDF files (*.pdf)|*.pdf",style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) as fileDialog:if fileDialog.ShowModal() == wx.ID_CANCEL:returnoutput_path = fileDialog.GetPath()try:merger = PyPDF2.PdfMerger()# Add all selected filesfor i in range(self.selected_listbox.GetCount()):file_path = self.selected_listbox.GetClientData(i)merger.append(file_path)# Write to output filemerger.write(output_path)merger.close()wx.MessageBox(f"PDF文件已成功合并为: {output_path}", "成功", wx.OK | wx.ICON_INFORMATION)except Exception as e:wx.MessageBox(f"合并PDF时出错: {str(e)}", "错误", wx.OK | wx.ICON_ERROR)

最后,合并 PDF 的操作由 on_merge 方法实现。用户选择了要合并的 PDF 文件后,程序会弹出文件保存对话框,询问用户保存合并后文件的位置。使用 PyPDF2.PdfMerger 将所有选择的 PDF 文件合并并保存。

运行结果

在这里插入图片描述


http://www.ppmy.cn/embedded/169004.html

相关文章

如何通过DeepBI提升亚马逊广告效果:全方位优化广告投放的智能工具

在竞争激烈的亚马逊市场上&#xff0c;精准的广告投放已成为商家成功的关键。传统的广告优化方法常常依赖手动调整和经验判断&#xff0c;这不仅耗时耗力&#xff0c;还容易忽视潜在的优化机会。随着人工智能技术的发展&#xff0c;DeepBI应运而生&#xff0c;成为提升亚马逊广…

001 Kafka入门及安装

Kafka入门及安装 文章目录 Kafka入门及安装1.介绍Kafka的基本概念和核心组件 2.安装1.docker快速安装zookeeper安装kafka安装 添加topic删除topickafka-ui安装 2.Docker安装&#xff08;SASL/PLAIN认证配置-用户名密码&#xff09; 来源参考的deepseek&#xff0c;如有侵权联系…

Python - Python操作Redis

安装Redis可参考 Redis-入门简介-CSDN博客 在Python中接入Redis数据库通常使用redis-py这个库 一、安装Redis 首先&#xff0c;需要安装redis-py库。通过pip来安装 pip install redis 二、连接Redis Redis连接操作import redisdef redis_connect():try:redisClient redi…

基于大数据的音乐网站数据分析与可视化推荐系统

【大数据】基于大数据的音乐网站数据分析与可视化推荐系统&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 本选题旨在设计并实现一款基于大数据技术的音乐网站数据分析与可视化推荐系统&#x…

AI数字人开发,引领科技新潮流

引言 随着人工智能技术的迅猛发展&#xff0c;AI 数字人在影视娱乐、客户服务、教育及医疗等多个领域展现出巨大的潜力。本文旨在为开发者提供一份详细的 AI 数字人系统开发指南&#xff0c;涵盖从基础架构到实现细节的各个方面&#xff0c;包括人物建模、动作生成、语音交互、…

在 IntelliJ IDEA 中启动多个注册到 Nacos 的服务

使用场景&#xff1a;边改代码&#xff0c;边和前端联调。 在微服务架构中&#xff0c;服务注册与发现是核心功能之一。Nacos 作为一款流行的开源服务注册与配置管理工具&#xff0c;被广泛应用于微服务架构中。本文将介绍如何在 IntelliJ IDEA 中配置并启动多个注册到 Nacos …

ArcGIS Pro技巧实战:高效矢量化天地图地表覆盖图

在地理信息系统&#xff08;GIS&#xff09;领域&#xff0c;地表覆盖图的矢量化是一项至关重要的任务。天地图作为中国国家级的地理信息服务平台&#xff0c;提供了丰富且详尽的地表覆盖数据。然而&#xff0c;这些数据通常以栅格格式存在&#xff0c;不利于进行空间分析和数据…

python模拟监测自动驾驶模拟过程中违反交通规则的车辆

以下是一个简单的 Python 示例&#xff0c;用于模拟监测自动驾驶模拟过程中违反交通规则的车辆。在这个示例中&#xff0c;我们假设交通规则包括车辆不能超过限速&#xff0c;并且不能在红灯时通过路口。 import random# 定义交通规则 SPEED_LIMIT 60 # 限速&#xff0c;单位…