import
tkinter as tk
from
tkinter
import
filedialog, messagebox, ttk
import
os
import
threading
from
queue
import
Queue
try
:
from
PyPDF2
import
PdfMerger
except
ModuleNotFoundError:
import
sys
sys.exit(
"Error: PyPDF2 模块未安装,请运行 'pip install PyPDF2' 进行安装"
)
class
PDFMergerApp:
def
__init__(
self
):
self
.window
=
tk.Tk()
self
.window.title(
'📄 PDF合并打印软件'
)
self
.window.geometry(
'700x450'
)
self
.window.configure(bg
=
'#F8FAFC'
)
self
.button_style
=
{
'background'
:
'#4F46E5'
,
'foreground'
:
'white'
,
'borderwidth'
:
0
,
'relief'
:
'flat'
,
'font'
: (
'微软雅黑'
,
12
,
'bold'
),
'padx'
:
30
,
'pady'
:
15
}
main_frame
=
tk.Frame(
self
.window, bg
=
'#FFFFFF'
)
main_frame.grid_columnconfigure(
0
, weight
=
1
)
main_frame.grid_rowconfigure(
1
, weight
=
1
)
main_frame.pack(expand
=
True
, fill
=
'both'
, padx
=
35
, pady
=
30
)
title_label
=
tk.Label(
main_frame,
text
=
'PDF文件合并工具'
,
font
=
(
'微软雅黑'
,
20
,
'bold'
),
fg
=
'#1E293B'
,
bg
=
'#FFFFFF'
,
pady
=
20
)
title_label.grid(row
=
0
, column
=
0
, sticky
=
'ew'
)
button_frame
=
tk.Frame(main_frame, bg
=
'#FFFFFF'
, padx
=
20
)
button_frame.grid(row
=
1
, column
=
0
, sticky
=
'ew'
)
button_frame.grid_columnconfigure(
0
, weight
=
1
)
select_button
=
tk.Button(
button_frame,
text
=
'🖇️ 选择并合并PDF文件'
,
command
=
self
.select_and_merge_pdfs,
cursor
=
'hand2'
,
*
*
self
.button_style
)
select_button.grid(row
=
0
, column
=
0
, pady
=
(
25
,
35
), sticky
=
'ew'
)
self
.status_label
=
tk.Label(main_frame,
text
=
'准备就绪'
,
font
=
(
'微软雅黑'
,
11
),
fg
=
'#64748B'
,
bg
=
'#FFFFFF'
,
padx
=
15
,
pady
=
12
)
self
.status_label.grid(row
=
2
, column
=
0
, pady
=
(
5
,
15
), sticky
=
'ew'
)
select_button.bind(
'<Enter>'
,
lambda
e: select_button.config(background
=
'#4338CA'
))
select_button.bind(
'<Leave>'
,
lambda
e: select_button.config(background
=
'#4F46E5'
))
try
:
self
.window.iconbitmap(
'pdf_icon.ico'
)
except
:
pass
self
.queue
=
Queue()
def
update_progress(
self
):
try
:
while
not
self
.queue.empty():
msg
=
self
.queue.get_nowait()
if
msg.startswith(
'status:'
):
self
.status_label[
'text'
]
=
msg.split(
':'
)[
1
]
elif
msg.startswith(
'error:'
):
messagebox.showerror(
'错误'
, f
'处理PDF时出错:{msg.split(":", 1)[1]}'
)
elif
msg
=
=
'done'
:
return
except
Queue.Empty:
pass
self
.window.after(
50
,
self
.update_progress)
def
merge_pdfs_thread(
self
, files):
try
:
merger
=
PdfMerger(strict
=
False
)
total_files
=
len
(files)
for
i, pdf_file
in
enumerate
(files,
1
):
with
open
(pdf_file,
'rb'
) as pdf:
merger.append(fileobj
=
pdf, import_outline
=
False
)
self
.queue.put(f
'status:正在处理: {os.path.basename(pdf_file)}'
)
output_path
=
os.path.join(os.path.dirname(files[
0
]),
'merged_output.pdf'
)
self
.queue.put(
'status:正在保存文件...'
)
with
open
(output_path,
'wb'
) as output:
merger.write(fileobj
=
output)
merger.close()
self
.queue.put(
'status:完成!'
)
os.startfile(output_path)
except
Exception as e:
self
.queue.put(f
'error:{str(e)}'
)
finally
:
self
.queue.put(
'done'
)
def
select_and_merge_pdfs(
self
):
files
=
filedialog.askopenfilenames(
title
=
'选择PDF文件'
,
filetypes
=
[(
'PDF files'
,
'*.pdf'
)]
)
if
files:
self
.status_label[
'text'
]
=
'准备处理...'
thread
=
threading.Thread(target
=
self
.merge_pdfs_thread, args
=
(files,))
thread.daemon
=
True
thread.start()
self
.window.after(
100
,
self
.update_progress)
def
run(
self
):
self
.window.mainloop()
if
__name__
=
=
'__main__'
:
app
=
PDFMergerApp()
app.run()