增加个图形界面的代码:
[Python] - import tkinter as tk
- from tkinter import ttk, filedialog, messagebox
- import PyPDF2
- from pathlib import Path
- import threading
- class PDFUnlockerGUI:
- def __init__(self, root):
- self.root = root
- self.root.title("PDF解锁工具")
- self.root.geometry("600x400")
- self.root.resizable(True, True)
-
- # 创建界面
- self.create_widgets()
-
- # 处理状态
- self.is_processing = False
-
- def create_widgets(self):
- """
- 创建界面组件
- """
- # 主框架
- main_frame = ttk.Frame(self.root, padding="10")
- main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
-
- # 配置网格权重
- self.root.columnconfigure(0, weight=1)
- self.root.rowconfigure(0, weight=1)
- main_frame.columnconfigure(1, weight=1)
-
- # 输入文件/目录选择
- ttk.Label(main_frame, text="选择文件或目录:").grid(row=0, column=0, sticky=tk.W, pady=5)
-
- self.path_var = tk.StringVar()
- self.path_entry = ttk.Entry(main_frame, textvariable=self.path_var)
- self.path_entry.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=(5, 5), pady=5)
-
- self.browse_button = ttk.Button(main_frame, text="浏览...", command=self.browse_path)
- self.browse_button.grid(row=0, column=2, padx=(5, 0), pady=5)
-
- # 进度条
- self.progress_var = tk.DoubleVar()
- self.progress_bar = ttk.Progressbar(main_frame, variable=self.progress_var, maximum=100)
- self.progress_bar.grid(row=1, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=10)
-
- # 状态标签
- self.status_var = tk.StringVar(value="就绪")
- self.status_label = ttk.Label(main_frame, textvariable=self.status_var)
- self.status_label.grid(row=2, column=0, columnspan=3, sticky=tk.W, pady=5)
-
- # 结果文本框
- self.result_text = tk.Text(main_frame, height=15, width=70)
- self.result_text.grid(row=3, column=0, columnspan=3, sticky=(tk.W, tk.E, tk.N, tk.S), pady=10)
-
- # 滚动条
- scrollbar = ttk.Scrollbar(main_frame, orient=tk.VERTICAL, command=self.result_text.yview)
- scrollbar.grid(row=3, column=3, sticky=(tk.N, tk.S))
- self.result_text.configure(yscrollcommand=scrollbar.set)
-
- # 开始按钮
- self.start_button = ttk.Button(main_frame, text="开始处理", command=self.start_processing)
- self.start_button.grid(row=4, column=1, pady=10)
-
- # 配置结果文本框的网格权重
- main_frame.rowconfigure(3, weight=1)
-
- def browse_path(self):
- """
- 浏览文件或目录
- """
- # 创建一个选择对话框
- file_path = filedialog.askopenfilename(
- title="选择PDF文件",
- filetypes=[("PDF files", "*.pdf"), ("All files", "*.*")]
- )
-
- if not file_path:
- # 如果没有选择文件,则尝试选择目录
- dir_path = filedialog.askdirectory(title="选择包含PDF文件的目录")
- if dir_path:
- self.path_var.set(dir_path)
- else:
- self.path_var.set(file_path)
-
- def copy_pdf_pages(self, input_path: str, output_path: str) -> bool:
- """
- 移除PDF文件的所有限制
-
- Args:
- input_path: 输入PDF文件路径
- output_path: 输出PDF文件路径
-
- Returns:
- 是否成功移除限制
- """
- try:
- with open(input_path, 'rb') as input_file:
- reader = PyPDF2.PdfReader(input_file)
-
- writer = PyPDF2.PdfWriter()
-
- # 复制所有页面
- for page in reader.pages:
- writer.add_page(page)
-
- # 写入新文件(不设置任何加密或限制)
- with open(output_path, 'wb') as output_file:
- writer.write(output_file)
-
- return True
-
- except Exception as e:
- self.result_text.insert(tk.END, f"处理文件 '{input_path}' 时发生错误: {e}\n")
- return False
-
- def process_files(self):
- """
- 在后台线程中处理文件
- """
- input_path = self.path_var.get().strip()
-
- if not input_path:
- messagebox.showerror("错误", "请选择要处理的文件或目录")
- self.is_processing = False
- return
-
- path_obj = Path(input_path)
-
- if not path_obj.exists():
- messagebox.showerror("错误", "指定的文件或目录不存在")
- self.is_processing = False
- return
-
- try:
- if path_obj.is_dir():
- files = list(path_obj.glob("**/*.pdf"))
- else:
- files = [path_obj]
-
- total = len(files)
- if total == 0:
- self.result_text.insert(tk.END, "未找到PDF文件\n")
- self.status_var.set("未找到PDF文件")
- self.is_processing = False
- return
-
- self.result_text.insert(tk.END, f"找到 {total} 个PDF文件\n")
- self.result_text.insert(tk.END, "=" * 50 + "\n")
-
- success_count = 0
- for i, pdf_file in enumerate(files, start=1):
- if not self.is_processing: # 用户取消操作
- break
-
- # 更新进度
- progress = (i / total) * 100
- self.progress_var.set(progress)
- self.status_var.set(f"正在处理: {pdf_file.name} ({i}/{total})")
- self.root.update_idletasks()
-
- if not pdf_file.is_file():
- self.result_text.insert(tk.END, f"跳过非PDF文件: {pdf_file}\n")
- continue
-
- output_file = pdf_file.with_name(f"{pdf_file.stem}_decrypt.pdf")
- success = self.copy_pdf_pages(pdf_file, output_file)
-
- if success:
- success_count += 1
- self.result_text.insert(tk.END, f"✓ {pdf_file.name} 处理成功\n")
- else:
- self.result_text.insert(tk.END, f"✗ {pdf_file.name} 处理失败\n")
-
- self.result_text.see(tk.END)
- self.root.update_idletasks()
-
- # 处理完成
- self.progress_var.set(100)
- self.status_var.set(f"处理完成: {success_count}/{total} 个文件成功处理")
- self.result_text.insert(tk.END, "=" * 50 + "\n")
- self.result_text.insert(tk.END, f"处理完成: {success_count}/{total} 个文件成功处理\n")
-
- except Exception as e:
- self.result_text.insert(tk.END, f"处理过程中发生错误: {e}\n")
- self.status_var.set("处理出错")
-
- finally:
- self.is_processing = False
- self.start_button.config(text="开始处理", state=tk.NORMAL)
-
- def start_processing(self):
- """
- 开始或停止处理
- """
- if self.is_processing:
- # 停止处理
- self.is_processing = False
- self.start_button.config(text="开始处理", state=tk.NORMAL)
- self.status_var.set("处理已停止")
- else:
- # 开始处理
- self.is_processing = True
- self.start_button.config(text="停止处理", state=tk.NORMAL)
- self.result_text.delete(1.0, tk.END)
- self.progress_var.set(0)
-
- # 在新线程中处理文件,避免阻塞GUI
- thread = threading.Thread(target=self.process_files)
- thread.daemon = True
- thread.start()
- def main():
- root = tk.Tk()
- app = PDFUnlockerGUI(root)
- root.mainloop()
- if __name__ == "__main__":
- main()
复制代码 |