当前位置: 首页 > news >正文

Python小工具之PDF合并

Python小工具之PDF合并

  • 1、Python小工具(PDF合并代码)
  • 2、打包代码生成exe文件
  • 3、打开小工具查看效果
  • 4、小工具下载链接

1、Python小工具(PDF合并代码)

import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
from PyPDF2 import PdfMerger,PdfReader
from threading import Thread
from PIL import Image, ImageTk class PDFMergerGUI:def __init__(self, master):self.master = mastermaster.title("PDF合并工具 v2.0")master.geometry("800x600")# 设置窗口图标self.set_window_icon()# 创建界面元素self.create_widgets()# 初始化变量self.files = []self.merging = Falsedef create_widgets(self):# 文件列表框架list_frame = ttk.LabelFrame(self.master, text="待合并文件列表")list_frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)# 文件列表self.tree = ttk.Treeview(list_frame,columns=("path", "pages"),show="headings",selectmode="extended")self.tree.heading("path", text="文件路径")self.tree.heading("pages", text="页数")self.tree.column("path", width=500)self.tree.column("pages", width=80)self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)# 滚动条scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.tree.yview)scrollbar.pack(side=tk.RIGHT, fill=tk.Y)self.tree.configure(yscrollcommand=scrollbar.set)# 操作按钮框架btn_frame = ttk.Frame(self.master)btn_frame.pack(pady=5, fill=tk.X)ttk.Button(btn_frame, text="添加文件", command=self.add_files).pack(side=tk.LEFT, padx=5)ttk.Button(btn_frame, text="移除选中", command=self.remove_files).pack(side=tk.LEFT, padx=5)ttk.Button(btn_frame, text="上移", command=lambda: self.move_items(-1)).pack(side=tk.LEFT, padx=5)ttk.Button(btn_frame, text="下移", command=lambda: self.move_items(1)).pack(side=tk.LEFT, padx=5)# 输出路径框架output_frame = ttk.Frame(self.master)output_frame.pack(pady=5, fill=tk.X, padx=10)ttk.Label(output_frame, text="输出文件:").pack(side=tk.LEFT)self.output_entry = ttk.Entry(output_frame, width=50)self.output_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)ttk.Button(output_frame, text="浏览...", command=self.select_output).pack(side=tk.LEFT)# 合并按钮self.merge_btn = ttk.Button(self.master,text="开始合并",command=self.start_merge,style="Accent.TButton")self.merge_btn.pack(pady=10)# 状态栏self.status = ttk.Label(self.master, text="就绪", relief=tk.SUNKEN)self.status.pack(side=tk.BOTTOM, fill=tk.X)def setup_drag_drop(self):# 支持拖放文件self.master.drop_target_register('*')self.master.dnd_bind('<<Drop>>', self.handle_drop)def handle_drop(self, event):files = self.master.tk.splitlist(event.data)self.add_files(files=[f for f in files if f.lower().endswith('.pdf')])def add_files(self, files=None):if not files:files = filedialog.askopenfilenames(filetypes=[("PDF文件", "*.pdf")],title="选择要合并的PDF文件")for f in files:if f not in self.files:self.files.append(f)self.tree.insert("", tk.END, values=(f, self.get_page_count(f)))self.update_status()def remove_files(self):selected = self.tree.selection()for item in selected:index = self.tree.index(item)del self.files[index]self.tree.delete(item)self.update_status()def move_items(self, direction):selected = self.tree.selection()if not selected:returnitems = [(self.tree.index(item), item) for item in selected]items.sort(reverse=direction > 0)for index, item in items:new_pos = index + directionif 0 <= new_pos < len(self.files):self.files.insert(new_pos, self.files.pop(index))self.tree.move(item, "", new_pos)def select_output(self):filename = filedialog.asksaveasfilename(defaultextension=".pdf",filetypes=[("PDF文件", "*.pdf")],initialfile="merged.pdf"  # 添加默认文件名)if filename:filename = os.path.abspath(filename)  # 转为绝对路径self.output_entry.delete(0, tk.END)self.output_entry.insert(0, filename)def get_page_count(self, filepath):"""获取PDF页数(带详细错误分类)"""try:with open(filepath, 'rb') as f:reader = PdfReader(f)if reader.is_encrypted:return ("🔒 加密", "orange")  # 返回元组(显示文本,标签样式)return (f"{len(reader.pages)}页")except PermissionError:return ("⛔ 无权限", "red")except Exception as e:print(f"页数获取错误 ({filepath}): {str(e)}")return ("❌ 错误", "red")def start_merge(self):if self.merging:returnoutput_path = self.output_entry.get()if not output_path:messagebox.showerror("错误", "请先选择输出路径")returnif len(self.files) < 1:messagebox.showerror("错误", "请添加要合并的PDF文件")returndef merge_thread():try:merger = PdfMerger()total = len(self.files)for i, f in enumerate(self.files, 1):if not os.path.exists(f):raise FileNotFoundError(f"文件不存在: {f}")merger.append(f)self.update_progress(i, total)os.makedirs(os.path.dirname(output_path), exist_ok=True)with open(output_path, 'wb') as f:merger.write(f)messagebox.showinfo("成功", f"合并完成!\n输出文件: {output_path}")except Exception as e:messagebox.showerror("错误", str(e))finally:merger.close()self.merging = Falseself.merge_btn.config(text="开始合并")self.status.config(text="就绪")self.merging = Trueself.merge_btn.config(text="合并中...")Thread(target=merge_thread, daemon=True).start()def update_progress(self, current, total):self.master.after(0, lambda: self.status.config(text=f"正在合并 ({current}/{total}): {os.path.basename(self.files[current - 1])}"))def update_status(self):self.status.config(text=f"已选择 {len(self.files)} 个PDF文件")def set_window_icon(self):"""设置窗口图标(支持PNG和ICO)"""try:# 优先尝试加载PNGimg = Image.open("pdf.ico")photo = ImageTk.PhotoImage(img)self.master.iconphoto(True, photo)except Exception as e:print(f"PNG图标加载失败: {str(e)}")try:# 备用ICO加载self.master.iconbitmap("pdf.ico")except Exception as e:print(f"ICO图标加载失败: {str(e)}")messagebox.showwarning("图标错误", "无法加载程序图标")if __name__ == "__main__":root = tk.Tk()style = ttk.Style(root)style.theme_use("clam")app = PDFMergerGUI(root)root.mainloop()

2、打包代码生成exe文件

pyinstaller --onefile --icon=pdf.ico --add-data="pdf.ico;." merge_pdf.py

3、打开小工具查看效果

在这里插入图片描述

4、小工具下载链接

下载: 请点击这里

http://www.lryc.cn/news/580353.html

相关文章:

  • 数据结构:多维数组在内存中的映射(Address Mapping of Multi-dimensional Arrays)
  • IDEA中application.yml配置文件不自动提示解决办法
  • 如何在IntelliJ IDEA中设置数据库连接全局共享
  • 从“电话催维修“到“手机看进度“——售后服务系统开发如何重构客户体验
  • CppCon 2018 学习:Surprises In Object Lifetime
  • Kotlin 协程:Channel 与 Flow 深度对比及 Channel 使用指南
  • 【ES6】Latex总结笔记生成器(网页版)
  • Jenkins Pipeline(二)
  • 【Elasticsearch】深度分页及其替代方案
  • 【openp2p】 学习2:源码阅读P2PNetwork和P2PTunnel
  • 【STM32实践篇】:GPIO 详解
  • 网络资源模板--基于Android Studio 实现的极简天气App
  • Excel 数据透视表不够用时,如何处理来自多个数据源的数据?
  • 动手实践OpenHands系列学习笔记1:Docker基础与OpenHands容器结构
  • Softhub软件下载站实战开发(十三):软件管理前端分片上传实现
  • 用户中心Vue3网页开发(1.0版)
  • Java零基础笔记01(JKD及开发工具IDEA安装配置)
  • Linux进程管理:从基础到实战
  • 60天python训练计划----day59
  • 数据结构:数组:插入操作(Insert)与删除操作(Delete)
  • 深度学习4(浅层神经网络)
  • 【深度学习】神经网络剪枝方法的分类
  • 由coalesce(1)OOM引发的coalesce和repartition理解
  • C++ 网络编程(15) 利用asio协程搭建异步服务器
  • Linux——进程(下)
  • android studio 配置硬件加速 haxm
  • spring中 方法上@Transation实现原理
  • C++20中的counting_semaphore的应用
  • C++ 模板参数匹配、特化
  • AtCoder AT_abc413_c [ABC413C] Large Queue 题解