当前位置: 首页 > 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.dtcms.com/a/267673.html

相关文章:

  • Redux 扩展与标准化模板方案
  • LINUX75 LAMP
  • 字节一面整理
  • C++ 模板参数匹配、特化
  • 智能监控算法助力工厂高温高效管理
  • 淘系怎么做?
  • hiredis window之RFDMap
  • 基于大模型的肾积水全周期预测与诊疗方案研究报告
  • 如何使用backtrace定位Linux程序的崩溃位置
  • 【STM32】定时器中断 + 含常用寄存器和库函数配置(提供完整实例代码)
  • 洛谷 P11967 [GESP202503 八级] 割裂-普及+/提高
  • 百度文心 4.5 大模型详解:ERNIE 4.5 Technical Report
  • 水下航行器外形之变体式与回转体的区别
  • 线程锁和线程同步
  • 从“电话催维修“到“手机看进度“——售后服务系统开发如何重构客户体验
  • Linux网络配置与故障排除完全指南
  • 12 nacos配置中心
  • 使用Kahn算法处理节点依赖关系
  • ABB焊接机器人智能节气仪
  • 汽车制造车间检测机器人与PLC无线以太网实时控制方案
  • 数据库学习笔记(十七)--触发器的使用
  • Java SE--数组
  • 前端相关性能优化笔记
  • TEXT Complete Search
  • 【RK3568 编译rtl8723DU驱动】
  • Write-up:hacker_dns
  • 安达发|告别低效排产:APS高级排程如何助力电池企业智造升级?
  • Java 大视界 -- 基于 Java 的大数据实时流处理在工业物联网设备能耗实时监测与节能优化中的应用(332)
  • 09_云原生架构:拥抱不确定性
  • 【力扣 简单 C】746. 使用最小花费爬楼梯