'''
一个将多个图片合并为一个PDF文件的python工具
#################################################################
主要功能:
1、用于将指定文件夹中的所有图片文件合并生成一个PDF文件。
2、支持jpg、png和bmp图片格式,自动过滤掉其它格式
3、实现图片预览
4、通过拖动,实现图片文件顺序的调整
5、输入或选择保存PDF的文件名和路径
6、指定PDF中图片模式(RGB,8位彩色或灰度,满足对不同用户对PDF文件大小的要求。
#################################################################
界面介绍:
界面使用box布局,一个垂直QVBox布局,包含个多行水平QHBox布局:
第1行:一个显示原始图片文件所在位置的文本框,一个打开文件夹选择对话框按钮,一个重新加截按钮,
第2行:左侧为一个显示指定文件夹内图片文件名的列表框,下面为一个删除按钮,右侧为一个图片,用于预览当前选中的图片文件
第4行:一个文本框,用于输入PDF文件保存位置,一个按钮用于选择文件保存位置,一个下拉列表,用于选择文件保存模式(RGB、8位彩色或灰度)
第5行:一个文本框,用于显示处理进度和处理信息。
第6行:一个居中的开始处理按钮
##################################################################
'''
import os
import sys
from PyQt5.QtCore import pyqtSignal, QThread
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import (QWidget, QPushButton,
QHBoxLayout, QVBoxLayout, QApplication, QLabel,
QLineEdit, QTextEdit, QComboBox, QFileDialog,
QListWidget, QListWidgetItem, QAbstractItemView
)
from PIL import Image
class Thread_do(QThread): # 定义线程类
# 定义带参数一个信号及所需参数
_signal =pyqtSignal(str)
#定义几个成员,用于传递参数,包括:源文件夹,目标文件名,保存模式和图像列表
_picpath=""
_trgfile=""
_picmode=""
_piclist=[]
#重写类线程类的初步化方法,用于将传入的几个参数保存到类成员中
def __init__(self,_path,_trg,_mode,_piclist):
super().__init__()
self._picpath=_path
self._trgfile=_trg
self._picmode=_mode
self._piclist=_piclist
def run(self):#线程的执行方法
list_images=[]#定义一个列表,用于保存每个图像对象
for i in range(len(self._piclist)):
fullPicname=self._picpath+"/"+self._piclist[i]
if self._picmode=="32位真彩":
list_images.append(Image.open(fullPicname).convert("RGB"))#32位真彩
if self._picmode == "8位彩色":
list_images.append(Image.open(fullPicname).convert("P")) # 8位彩色
if self._picmode == "灰度":
list_images.append(Image.open(fullPicname).convert("L")) # 灰度
self._signal.emit("处理..."+fullPicname+"...完成") ##返回处理
# 因为PIL保存为PDF的格式为:
#第一个图像对象.save(目标文件名,保存参数,其它图片对象列表)
#所以要把第一个图像对象从列表中剔除,并赋值给另一个图像对象(im1)
im1=list_images.pop(0)
im1.save(self._trgfile, save_all=True, append_images=list_images)
self._signal.emit("全部完成")##返回全部完成信号
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
#定义布局
vbox = QVBoxLayout()
hbox_line1 = QHBoxLayout()
hbox_line2 = QHBoxLayout()
hbox_line3 = QHBoxLayout()
hbox_line4 = QHBoxLayout()
hbox_line5 = QHBoxLayout()
#第一行,一个标签,一个文件框,一个打开对话框按钮,一个重载按钮
######################################################
self.txt_SrcPath = QLineEdit("D:/") # 原始文件所在位置,默认为C:/
self.txt_SrcPath.setReadOnly(True)#设置为不可编辑
btn_openDiagSrcPath = QPushButton("...") # 选择源文件夹按钮
#绑定按钮的打开事件
btn_openDiagSrcPath.clicked.connect(self.showDialog_Src)
hbox_line1.addWidget(QLabel("图片路径:"))
hbox_line1.addWidget(self.txt_SrcPath)
hbox_line1.addWidget(btn_openDiagSrcPath)
#第二行,一个垂直布局(上面为一个图片文件列表,下面为操作按钮)一个用于显示当前选中的图片
vbox_s1=QVBoxLayout()
self.pic_listbox = QListWidget(self)
self.pic_listbox.setMaximumHeight(300)
self.pic_listbox.setMinimumHeight(300)
# 使列表框中的元素可拖动并设置拖动模式
self.pic_listbox.setAcceptDrops(True)
self.pic_listbox.setDragDropMode(QAbstractItemView.InternalMove)
#绑定列表框中列表项点击的事件(更新预览图片的显示内容)
self.pic_listbox.itemClicked.connect(self.listItemClick)
btn_del=QPushButton("移除选中的文件")
#绑定删除按钮的事件
btn_del.clicked.connect(self.deleteListItem)
vbox_s1.addWidget(self.pic_listbox)
vbox_s1.addWidget(btn_del)
hbox_line2.addLayout(vbox_s1)
# 添加一个图片,用于显示选中的图片
self.lbl_Image = QLabel(self)
#固定预览图片的大小,可以进一步细化为根据宽度自动适应图片比例
self.lbl_Image.setMinimumSize(480,360)
self.lbl_Image.setMaximumSize(480,360)
self.lbl_Image.setText("暂未选择文件")
self.lbl_Image.setScaledContents(True)
hbox_line2.addWidget(self.lbl_Image)
#第3行,一个保存PDF存放位置的文本框,一个按钮用于打开文件选择对话框,
# 一个下拉列表:选择PDF保存模式:真彩、8位彩色或灰度。
self.txt_PDFPath = QLineEdit("D:/newFile.pdf") # PDF文件默认保存位置和文件名
btn_openDiagPDFFile = QPushButton("...") # 选择目标文件按钮
# 绑定按钮的打开事件
btn_openDiagPDFFile.clicked.connect(self.showDialog_Tgt)
#下拉列表框:图片模式:
self.list_PicFmt = QComboBox() # 定义下拉框,并添加三个图片格式选项
self.list_PicFmt.addItem("32位真彩")
self.list_PicFmt.addItem("8位彩色")
self.list_PicFmt.addItem("灰度")
self.list_PicFmt.setMaximumWidth(140)
self.list_PicFmt.setMinimumWidth(140)
hbox_line3.addWidget(QLabel("PDF路径和文件名:"))
hbox_line3.addWidget(self.txt_PDFPath)
hbox_line3.addWidget(btn_openDiagPDFFile)
hbox_line3.addWidget(QLabel("PDF文件色彩模式:"))
hbox_line3.addWidget(self.list_PicFmt)
#第四行,处理信息文本框
self.txt_PressInof = QTextEdit() # 处理信息文本框
hbox_line4.addWidget(self.txt_PressInof)
#第五行,生成按钮
self.btn_do = QPushButton("立即生成") # 处理按钮
hbox_line5.addWidget(self.btn_do)
#绑定生成按钮的事件
self.btn_do.clicked.connect(self.process_Pic)
#把几个水平布局加入到垂直布局器中
vbox.addLayout(hbox_line1)
vbox.addLayout(hbox_line2)
vbox.addLayout(hbox_line3)
vbox.addLayout(hbox_line4)
vbox.addLayout(hbox_line5)
self.setLayout(vbox)
#设置窗口大小(1027*720)及初始化位置(100,100)
self.setGeometry(100, 100, 1024, 720)
self.setWindowTitle('PIC2PDF')#设置标题
self.show()
d