5 changed files with 160 additions and 0 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,160 @@ |
|||
import tkinter as tk |
|||
from tkinter import ttk, filedialog, messagebox |
|||
import os |
|||
import subprocess |
|||
import threading |
|||
|
|||
# 拖拽支持(Windows) |
|||
try: |
|||
from tkinterdnd2 import DND_FILES, TkinterDnD |
|||
DND_AVAILABLE = True |
|||
except: |
|||
DND_AVAILABLE = False |
|||
|
|||
|
|||
class PDFCompressorApp: |
|||
def __init__(self, root): |
|||
self.root = root |
|||
self.root.title("Snail PDF压缩工具") |
|||
self.root.geometry("650x450") |
|||
|
|||
self.files = [] |
|||
self.quality_map = { |
|||
"极限压缩(低质量)": "/screen", |
|||
"标准压缩(推荐)": "/ebook", |
|||
"高质量(打印)": "/printer" |
|||
} |
|||
|
|||
self.create_widgets() |
|||
|
|||
def create_widgets(self): |
|||
frame = tk.Frame(self.root) |
|||
frame.pack(fill="both", expand=True, padx=10, pady=10) |
|||
|
|||
# 文件列表 |
|||
self.listbox = tk.Listbox(frame, height=12) |
|||
self.listbox.pack(fill="both", expand=True) |
|||
|
|||
# 拖拽支持 |
|||
if DND_AVAILABLE: |
|||
self.listbox.drop_target_register(DND_FILES) |
|||
self.listbox.dnd_bind("<<Drop>>", self.drop_files) |
|||
|
|||
# 按钮区 |
|||
btn_frame = tk.Frame(frame) |
|||
btn_frame.pack(pady=5) |
|||
|
|||
tk.Button(btn_frame, text="添加文件", command=self.add_files).pack(side="left", padx=5) |
|||
tk.Button(btn_frame, text="添加文件夹", command=self.add_folder).pack(side="left", padx=5) |
|||
tk.Button(btn_frame, text="清空", command=self.clear_files).pack(side="left", padx=5) |
|||
|
|||
# 压缩质量 |
|||
tk.Label(frame, text="压缩质量:").pack() |
|||
self.quality = tk.StringVar(value="标准压缩(推荐)") |
|||
ttk.Combobox( |
|||
frame, |
|||
textvariable=self.quality, |
|||
values=list(self.quality_map.keys()) |
|||
).pack() |
|||
|
|||
# 进度条 |
|||
self.progress = ttk.Progressbar(frame, length=600) |
|||
self.progress.pack(pady=10) |
|||
|
|||
# 状态 |
|||
self.status = tk.Label(frame, text="等待开始") |
|||
self.status.pack() |
|||
|
|||
# 开始按钮 |
|||
tk.Button(frame, text="开始压缩", bg="green", fg="white", |
|||
command=self.start).pack(pady=10) |
|||
|
|||
def add_files(self): |
|||
files = filedialog.askopenfilenames(filetypes=[("PDF Files", "*.pdf")]) |
|||
self.add_to_list(files) |
|||
|
|||
def add_folder(self): |
|||
folder = filedialog.askdirectory() |
|||
if folder: |
|||
pdfs = [os.path.join(folder, f) for f in os.listdir(folder) if f.lower().endswith(".pdf")] |
|||
self.add_to_list(pdfs) |
|||
|
|||
def add_to_list(self, files): |
|||
for f in files: |
|||
if f not in self.files: |
|||
self.files.append(f) |
|||
self.listbox.insert(tk.END, f) |
|||
|
|||
def drop_files(self, event): |
|||
files = self.root.tk.splitlist(event.data) |
|||
self.add_to_list(files) |
|||
|
|||
def clear_files(self): |
|||
self.files.clear() |
|||
self.listbox.delete(0, tk.END) |
|||
|
|||
def start(self): |
|||
if not self.files: |
|||
messagebox.showwarning("提示", "请先添加PDF文件") |
|||
return |
|||
|
|||
threading.Thread(target=self.compress_all, daemon=True).start() |
|||
|
|||
def compress_all(self): |
|||
gs_path = os.path.join(os.getcwd(), "bin", "gswin64c.exe") |
|||
|
|||
if not os.path.exists(gs_path): |
|||
messagebox.showerror("错误", "未找到 bin/gswin64c.exe(请检查Ghostscript绿色版)打包后的exe文件放置SnailPDF目录下运行") |
|||
return |
|||
|
|||
total = len(self.files) |
|||
self.progress["maximum"] = total |
|||
|
|||
for i, file in enumerate(self.files): |
|||
output = file.replace(".pdf", "_compressed.pdf") |
|||
|
|||
try: |
|||
before_size = os.path.getsize(file) |
|||
|
|||
cmd = [ |
|||
gs_path, |
|||
"-sDEVICE=pdfwrite", |
|||
"-dCompatibilityLevel=1.4", |
|||
f"-dPDFSETTINGS={self.quality_map[self.quality.get()]}", |
|||
"-dNOPAUSE", |
|||
"-dBATCH", |
|||
f"-sOutputFile={output}", |
|||
file |
|||
] |
|||
|
|||
subprocess.run( |
|||
cmd, |
|||
capture_output=True, |
|||
text=True, |
|||
creationflags=subprocess.CREATE_NO_WINDOW |
|||
) |
|||
after_size = os.path.getsize(output) |
|||
ratio = (1 - after_size / before_size) * 100 |
|||
|
|||
self.status.config( |
|||
text=f"完成: {os.path.basename(file)} | 压缩率: {ratio:.1f}%" |
|||
) |
|||
|
|||
except Exception as e: |
|||
self.status.config(text=f"失败: {os.path.basename(file)}") |
|||
|
|||
self.progress["value"] = i + 1 |
|||
|
|||
messagebox.showinfo("完成", "全部压缩完成!") |
|||
|
|||
|
|||
if __name__ == "__main__": |
|||
if DND_AVAILABLE: |
|||
root = TkinterDnD.Tk() |
|||
else: |
|||
root = tk.Tk() |
|||
|
|||
app = PDFCompressorApp(root) |
|||
root.mainloop() |
|||
|
|||
#打包命令 .\python.exe -m PyInstaller --onefile --windowed --icon=icon.ico --name "SnailSend" .\main.py |
|||
Loading…
Reference in new issue