PyQt5从入门到实践——Chapter15 明日图片助手

概述

使用Python开发一个明日图片助手软件,使用该软件批量对图片进行处理。

1. 需求及系统设计

1.1 明日图片助手软件具备的功能

批量添加文字水印、图片水印,添加水印时可设置位置和透明度,添加文字水印时可以设置字体和大小;能够将图片文件批量转化为大写或者小写,能够按照指定模板对文件进行重命名,并按照一定规律进行编号,可以预览选择的图片文件,实现良好的人机交互界面。

1.2 系统设计

系统功能结构:


系统业务流程:

2. 主窗口设计

2.1 Qt Designer中设计主窗口

设计菜单栏并添加子菜单图标(icon下添加)

主菜单栏下两个子菜单——添加水印;批量重命名

关于菜单栏下一个子菜单——关于本软件

2.2 优化主窗口

(1)设置窗体背景图片

#设置窗体背景图片
# MainWindow.setStyleSheet('#MainWindow{border-image:url(img/back.png)}')  # 设置背景图片
palette = QtGui.QPalette()
palette.setBrush(MainWindow.backgroundRole(),QBrush(QPixmap("img/back.png").scaled(MainWindow.size(), QtCore.Qt.IgnoreAspectRatio,QtCore.Qt.SmoothTransformation)))
MainWindow.setPalette(palette)
MainWindow.setAutoFillBackground(True)  # 设置自动填充背景

(2)设置窗体固定大小(不允许调整且最大化不可用)

#固定窗体大小
MainWindow.setFixedSize(800,600)

(3)定义子菜单(注意需要导入各窗体)

   #打开添加水印窗体
    def openMark(self):
        self.another = imageMark.Ui_MarkWindow()  # 创建水印窗体对象
        self.another.show()  # 显示窗体

    #打开重命名窗口
    def openRename(self):
        self.another = imageRename.Ui_RenameWindow()  # 创建重命名窗体对象
        self.another.show()  # 显示窗体


    #实现“关于本软件功能”
    def about(self):
        QMessageBox.information(None, '关于本软件', '图片批量处理器是一款提供日常工作的工具软件,'
                                               '通过该软件,您可以方便的为图片添加文字水印和图片水印,'
                                               '而且可以自定义添加位置,以及透明度;另外,您还可以通过'
                                               '该软件对图片文件进行重命名,支持文件名大写、小写,以及'
                                               '根据自定义模板对图片文件进行编号。', QMessageBox.Ok)

完整main.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'main.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from PyQt5.QtGui import QBrush, QPixmap
from PyQt5.QtWidgets import QMessageBox
import imageMark,imageRename


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 541, 27))
        self.menubar.setObjectName("menubar")
        self.menu = QtWidgets.QMenu(self.menubar)
        self.menu.setSeparatorsCollapsible(False)
        self.menu.setObjectName("menu")
        self.menu_2 = QtWidgets.QMenu(self.menubar)
        self.menu_2.setObjectName("menu_2")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.action_mark = QtWidgets.QAction(MainWindow)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("img/mark.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.action_mark.setIcon(icon)
        self.action_mark.setObjectName("action_mark")
        self.action_rename = QtWidgets.QAction(MainWindow)
        icon1 = QtGui.QIcon()
        icon1.addPixmap(QtGui.QPixmap("img/rename.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.action_rename.setIcon(icon1)
        self.action_rename.setObjectName("action_rename")
        self.action_about = QtWidgets.QAction(MainWindow)
        icon2 = QtGui.QIcon()
        icon2.addPixmap(QtGui.QPixmap("img/about.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.action_about.setIcon(icon2)
        self.action_about.setObjectName("action_about")
        self.menu.addAction(self.action_mark)
        self.menu.addAction(self.action_rename)
        self.menu_2.addAction(self.action_about)
        self.menubar.addAction(self.menu.menuAction())
        self.menubar.addAction(self.menu_2.menuAction())

        #设置窗体背景图片
        # MainWindow.setStyleSheet('#MainWindow{border-image:url(D:/work_lab/pyqt5/Learing2prac/Chapter15/img/back.png)}')  # 设置背景图片
        palette = QtGui.QPalette()
        palette.setBrush(MainWindow.backgroundRole(), QBrush(QPixmap("img/back.png").scaled(MainWindow.size(), QtCore.Qt.IgnoreAspectRatio,QtCore.Qt.SmoothTransformation)))
        MainWindow.setPalette(palette)
        MainWindow.setAutoFillBackground(True)  # 设置自动填充背景

        #固定窗体大小
        MainWindow.setFixedSize(800,600)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    #打开添加水印窗体
    def openMark(self):
        self.another = imageMark.Ui_MarkWindow()  # 创建水印窗体对象
        self.another.show()  # 显示窗体

    #打开重命名窗口
    def openRename(self):
        self.another = imageRename.Ui_RenameWindow()  # 创建重命名窗体对象
        self.another.show()  # 显示窗体


    #实现“关于本软件功能”
    def about(self):
        QMessageBox.information(None, '关于本软件', '图片批量处理器是一款提供日常工作的工具软件,'
                                               '通过该软件,您可以方便的为图片添加文字水印和图片水印,'
                                               '而且可以自定义添加位置,以及透明度;另外,您还可以通过'
                                               '该软件对图片文件进行重命名,支持文件名大写、小写,以及'
                                               '根据自定义模板对图片文件进行编号。', QMessageBox.Ok)


    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "明日图片助手"))
        self.menu.setTitle(_translate("MainWindow", "主菜单"))
        self.menu_2.setTitle(_translate("MainWindow", "关于"))
        self.action_mark.setText(_translate("MainWindow", "添加水印"))
        self.action_rename.setText(_translate("MainWindow", "批量重命名"))
        self.action_about.setText(_translate("MainWindow", "关于本软件"))

        self.action_about.triggered.connect(self.about) #关联”关于本软件“子菜单
        self.action_mark.triggered.connect(self.openMark) #关联”添加水印“子菜单
        self.action_rename.triggered.connect(self.openRename) #关联”批量重命名“子菜单

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

3. 添加水印设计

完整imageMark.py

import os
import os.path
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMessageBox,QFileDialog,QFontDialog,QMainWindow
from PyQt5.QtGui import QFontMetrics,QFontInfo
from PIL import Image, ImageDraw, ImageFont,ImageEnhance

class Ui_MarkWindow(QMainWindow):

    # 构造方法
    def __init__(self):
        super(Ui_MarkWindow, self).__init__()
        self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint)  # 只显示关闭按钮
        self.setupUi(self) # 初始化窗体设置

    # 自动生成的代码,用来对窗体进行设置
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(578, 418)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        # 设置图片显示列表
        self.listWidget = QtWidgets.QListWidget(self.centralwidget)
        self.listWidget.setGeometry(QtCore.QRect(0, 0, 141, 391))
        self.listWidget.setObjectName("listWidget")
        # 设置加载图片按钮
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(150, 0, 75, 23))
        self.pushButton.setObjectName("pushButton")

        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(150, 30, 421, 151))
        self.groupBox.setObjectName("groupBox")

        # 设置文字水印单选按钮
        self.radioButton = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton.setGeometry(QtCore.QRect(20, 20, 101, 16))
        self.radioButton.setChecked(True)# 默认选中
        self.radioButton.setObjectName("radioButton")

        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(30, 50, 54, 16))
        self.label.setObjectName("label")

        # 设置要输入水印文字的文本框
        self.lineEdit = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit.setGeometry(QtCore.QRect(90, 50, 241, 20))
        self.lineEdit.setObjectName("lineEdit")

        # 设置“字体设置”按钮
        self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_2.setGeometry(QtCore.QRect(340, 50, 75, 23))
        self.pushButton_2.setObjectName("pushButton_2")

        # 设置图片水印单选按钮
        self.radioButton_2 = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton_2.setGeometry(QtCore.QRect(20, 80, 91, 16))
        self.radioButton_2.setChecked(False)# 默认不选中
        self.radioButton_2.setObjectName("radioButton_2")

        # 设置选择水印图片按钮
        self.pushButton_3 = QtWidgets.QPushButton(self.groupBox)
        self.pushButton_3.setGeometry(QtCore.QRect(340, 110, 75, 23))
        self.pushButton_3.setObjectName("pushButton_3")

        self.label_2 = QtWidgets.QLabel(self.groupBox)
        self.label_2.setGeometry(QtCore.QRect(30, 110, 54, 16))
        self.label_2.setObjectName("label_2")

        # 设置显示水印图片路径的文本框
        self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_2.setGeometry(QtCore.QRect(90, 110, 241, 20))
        self.lineEdit_2.setObjectName("lineEdit_2")

        self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_2.setGeometry(QtCore.QRect(150, 190, 421, 71))
        self.groupBox_2.setObjectName("groupBox_2")

        self.label_3 = QtWidgets.QLabel(self.groupBox_2)
        self.label_3.setGeometry(QtCore.QRect(270, 31, 54, 21))
        self.label_3.setObjectName("label_3")

        # 设置水印位置选择框
        self.comboBox = QtWidgets.QComboBox(self.groupBox_2)
        self.comboBox.setGeometry(QtCore.QRect(330, 30, 71, 22))
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem('左上角')
        self.comboBox.addItem('右上角')
        self.comboBox.addItem('左下角')
        self.comboBox.addItem('右下角')
        self.comboBox.addItem('居中位置')
        self.comboBox.setCurrentIndex(0)# 设置默认选择第一项

        self.label_4 = QtWidgets.QLabel(self.groupBox_2)
        self.label_4.setGeometry(QtCore.QRect(20, 30, 51, 21))
        self.label_4.setObjectName("label_4")

        # 设置水印透明度的滑动条
        self.horizontalSlider = QtWidgets.QSlider(self.groupBox_2)
        self.horizontalSlider.setGeometry(QtCore.QRect(70, 30, 181, 22))
        self.horizontalSlider.setMinimum(1)
        self.horizontalSlider.setMaximum(10)
        self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider.setObjectName("horizontalSlider")

        self.groupBox_3 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_3.setGeometry(QtCore.QRect(150, 270, 421, 71))
        self.groupBox_3.setObjectName("groupBox_3")

        self.label_6 = QtWidgets.QLabel(self.groupBox_3)
        self.label_6.setGeometry(QtCore.QRect(20, 30, 61, 21))
        self.label_6.setObjectName("label_6")

        # 设置显示保存路径的文本框
        self.lineEdit_3 = QtWidgets.QLineEdit(self.groupBox_3)
        self.lineEdit_3.setGeometry(QtCore.QRect(80, 30, 241, 20))
        self.lineEdit_3.setObjectName("lineEdit_3")

        # 设置选择图片保存路径的按钮
        self.pushButton_4 = QtWidgets.QPushButton(self.groupBox_3)
        self.pushButton_4.setGeometry(QtCore.QRect(330, 30, 75, 23))
        self.pushButton_4.setObjectName("pushButton_4")

        #设置执行按钮
        self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_5.setGeometry(QtCore.QRect(480, 350, 75, 23))
        self.pushButton_5.setObjectName("pushButton_5")

        MainWindow.setCentralWidget(self.centralwidget)
        #设置状态栏
        self.statusBar = QtWidgets.QStatusBar(MainWindow)
        self.statusBar.setObjectName("statusBar")
        self.statusBar.showMessage('准备就绪…… ')  # 设置状态栏默认值
        MainWindow.setStatusBar(self.statusBar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    # 自动生成的代码,用来设置窗体中控件的默认值
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "图片批量添加水印"))
        self.pushButton.setText(_translate("MainWindow", "加载图片"))
        self.groupBox.setTitle(_translate("MainWindow", "水印设置"))
        self.radioButton.setText(_translate("MainWindow", "添加文字水印"))
        self.label.setText(_translate("MainWindow", "水印文字:"))
        self.pushButton_2.setText(_translate("MainWindow", "字体设置"))
        self.radioButton_2.setText(_translate("MainWindow", "添加图片水印"))
        self.pushButton_3.setText(_translate("MainWindow", "浏览"))
        self.label_2.setText(_translate("MainWindow", "水印图片:"))
        self.groupBox_2.setTitle(_translate("MainWindow", "透明度及位置设置"))
        self.label_3.setText(_translate("MainWindow", "水印位置:"))
        self.label_4.setText(_translate("MainWindow", "透明度:"))
        self.groupBox_3.setTitle(_translate("MainWindow", "路径设置"))
        self.label_6.setText(_translate("MainWindow", "保存位置:"))
        self.pushButton_4.setText(_translate("MainWindow", "浏览"))
        self.pushButton_5.setText(_translate("MainWindow", "执行"))
        # 关联“加载图片”按钮的方法
        self.pushButton.clicked.connect(self.getFiles)
        # 关联“字体设置”按钮的方法
        self.pushButton_2.clicked.connect(self.setFont)
        # 关联“选择图片”按钮的方法
        self.pushButton_3.clicked.connect(self.setImg)
        # 关联“选择保存路径”按钮的方法
        self.pushButton_4.clicked.connect(self.msg)
        # 关联“执行”按钮的方法
        self.pushButton_5.clicked.connect(self.addMark)
        # 关联列表单击方法,用来预览选中的图片
        self.listWidget.itemClicked.connect(self.itemClick)

    # 设置字体
    def setFont(self):
        self.waterfont, ok = QFontDialog.getFont()  # 显示字体对话框
        if ok:  # 判断是否选择了字体
            self.lineEdit.setFont(self.waterfont)  # 设置水印文字的字体
            self.fontSize = QFontMetrics(self.waterfont) # 获取字体尺寸
            self.fontInfo = QFontInfo(self.waterfont) # 获取字体信息

    # 是否为图片
    def isImg(self,file):
        file = file.lower()
        if file == '.jpg':
            return True
        elif file == '.png':
            return True
        elif file == '.jpeg':
            return True
        elif file == '.bmp':
            return True
        else:
            return False

    # 获取所有文件
    def getFiles(self):
        try:
            # 选择图片文件夹路径
            self.img_path = QFileDialog.getExistingDirectory(None, "选择图片文件夹路径", os.getcwd())
            self.list = os.listdir(self.img_path) # 遍历选择的文件夹
            num=0   # 记录图片数量
            self.listWidget.clear()   # 清空列表项
            for i in range(0, len(self.list)): # 遍历图片列表
                filepath = os.path.join(self.img_path, self.list[i]) # 记录遍历到的文件名
                if os.path.isfile(filepath): # 判断是否为文件
                    imgType = os.path.splitext(filepath)[1]# 获取扩展名
                    if self.isImg(imgType): # 判断是否为图片
                        num += 1 # 数量加1
                        self.item = QtWidgets.QListWidgetItem(self.listWidget)  # 创建列表项
                        self.item.setText(self.list[i])  # 显示图片列表
            self.statusBar.showMessage('共有图片 '+str(num)+' 张')# 显示图片总数
        except Exception:
            QMessageBox.warning(None, '警告', '请选择一个有效路径……', QMessageBox.Ok)

    # 预览图片
    def itemClick(self, item):
        os.startfile(self.img_path + '\\' + item.text())

    # 选择水印图片
    def setImg(self):
        try:
            # waterimg即为选择的水印图片,第二形参为对话框标题,第三个为对话框打开后默认的路径
            self.waterimg = QFileDialog.getOpenFileName(None,'选择水印图片','C:\\',"图片文件(*.jpeg;*.png;*.jpg;*.bmp)")
            self.lineEdit_2.setText(self.waterimg[0]) # 显示选择的水印图片
        except Exception as e:
            print(e)

    # 选择保存路径
    def msg(self):
        try:
            # dir_path即为选择的文件夹的绝对路径,第二形参为对话框标题,第三个为对话框打开后默认的路径
            self.dir_path = QFileDialog.getExistingDirectory(None, "选择路径", os.getcwd())
            self.lineEdit_3.setText(self.dir_path)# 显示选择的保存路径
        except Exception as e:
            print(e)

    # 文字水印
    def textMark(self,img,newImgPath):
        try:
            im = Image.open(img).convert('RGBA') # 打开原始图片,并转换为RGBA
            newImg = Image.new('RGBA', im.size, (255, 255, 255, 0)) # 存储添加水印后的图片
            # 创建字体,说明:默认使用楷体,如果需要使用其他字体,需要将字体文件复制到当前目录中
            # 然后对下面第一个参数进行修改,可以使用self.fontInfo.family()动态获取字体名称,后面加扩展名即可
            font = ImageFont.truetype('simkai.ttf', self.fontInfo.pointSize())
            imagedraw = ImageDraw.Draw(newImg) # 创建绘制对象
            imgwidth, imgheight = im.size # 记录图片大小
            txtwidth = self.fontSize.maxWidth() * len(self.lineEdit.text()) # 获取字体宽度
            txtheight = self.fontSize.height() # 获取字体高度

            # 设置水印文字位置
            if self.comboBox.currentText() == '左上角':
                position=(0,0)
            elif  self.comboBox.currentText() == '左下角':
                position=(0,imgheight - txtheight)
            elif  self.comboBox.currentText() == '右上角':
                position=(imgwidth - txtwidth,0)
            elif  self.comboBox.currentText() == '右下角':
                position=(imgwidth - txtwidth, imgheight - txtheight)
            elif  self.comboBox.currentText() == '居中位置':
                position=(imgwidth/2,imgheight/2)
            # 设置文本颜色
            imagedraw.text(position, self.lineEdit.text(), font=font, fill="#FCA454")
            # 设置透明度
            alpha = newImg.split()[3]
            alpha = ImageEnhance.Brightness(alpha).enhance(int(self.horizontalSlider.value())/10.0)
            newImg.putalpha(alpha)
            Image.alpha_composite(im, newImg).save(newImgPath) # 保存图片
        except Exception:
            QMessageBox.warning(None, '错误', '图片格式有误,请重新选择……', QMessageBox.Ok)

    # 图片水印
    def imgMark(self,img,newImgPath):
        im = Image.open(img) # 打开原始图片
        mark = Image.open(self.lineEdit_2.text()) # 打开水印图片
        rgbaim = im.convert('RGBA') # 将原始图片转换为RGBA
        rgbamark = mark.convert('RGBA') # 将水印图片转换为RGBA
        imgwidth, imgheight = rgbaim.size # 获取原始图片尺寸
        nimgwidth, nimgheight = rgbamark.size # 获取水印图片尺寸
        # 缩放水印图片
        scale = 10
        markscale = max(imgwidth / (scale * nimgwidth), imgheight / (scale * nimgheight))
        newsize = (int(nimgwidth * markscale), int(nimgheight * markscale)) # 计算新的尺寸大小
        rgbamark = rgbamark.resize(newsize, resample=Image.ANTIALIAS) # 重新设置水印图片大小
        nimgwidth, nimgheight = rgbamark.size # 获取水印图片缩放后的尺寸
        # 计算水印位置
        if self.comboBox.currentText() == '左上角':
            position=(0,0)
        elif  self.comboBox.currentText() == '左下角':
            position=(0,imgheight - nimgheight)
        elif  self.comboBox.currentText() == '右上角':
            position=(imgwidth - nimgwidth,0)
        elif  self.comboBox.currentText() == '右下角':
            position=(imgwidth - nimgwidth, imgheight - nimgheight)
        elif  self.comboBox.currentText() == '居中位置':
            position=(int(imgwidth/2),int(imgheight/2))
        # 设置透明度:img.point(function)接受一个参数,且对图片中的每一个点执行这个函数,这个函数是一个匿名函数,使用lambda表达式来完成
        # convert()函数,用于不同模式图像之间的转换,模式“L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。
        # 在PIL中,从模式“RGB”转换为“L”模式是按照下面的公式转换的:L = R * 299/1000 + G * 587/1000+ B * 114/1000
        rgbamarkpha = rgbamark.convert("L").point(lambda x: x/int(self.horizontalSlider.value()))
        rgbamark.putalpha(rgbamarkpha)
        # 水印位置
        rgbaim.paste(rgbamark, position, rgbamarkpha)
        try:
            rgbaim.save(newImgPath) # 保存水印图片
        except Exception:
            QMessageBox.warning(None, '错误', '请选择其他路径……', QMessageBox.Ok)

    # 添加水印
    def addMark(self):
        if self.lineEdit_3.text() == '': # 判断是否选择了保存路径
            QMessageBox.warning(None,'警告','请选择保存路径',QMessageBox.Ok)
            return
        else:
            num = 0  # 记录处理图片数量
            for i in range(0, self.listWidget.count()): # 遍历图片列表
                # 设置原始图片路径(包括文件名)
                filepath = os.path.join(self.img_path, self.listWidget.item(i).text())
                # 设置水印图片保存路径(包括文件名)
                newfilepath = os.path.join(self.lineEdit_3.text(), self.listWidget.item(i).text())
                if self.radioButton.isChecked(): # 判断是否选择文字水印单选按钮
                    if self.lineEdit.text() == '': # 判断是否输入了水印文字
                        QMessageBox.warning(None, '警告', '请输入水印文字', QMessageBox.Ok)
                        return
                    else:
                        self.textMark(filepath,newfilepath) # 调用textMark方法添加文字水印
                        num += 1 # 处理图片数量加1
                else:
                    if self.lineEdit_2.text() != '': # 判断水印图片不为空
                        self.imgMark(filepath,newfilepath) # 调用imgMark方法添加图片水印
                        num += 1 # 处理图片数量加1
                    else:
                        QMessageBox.warning(None, '警告', '请选择水印图片', QMessageBox.Ok)
            self.statusBar.showMessage('任务完成,此次共处理 ' + str(num) + ' 张图片')  # 显示处理图片总数

4. 批量重命名设计

完整imageRename.py

import os
import os.path
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow,QFileDialog,QMessageBox
import imageMark # 导入模块

class Ui_RenameWindow(QMainWindow):

    # 构造方法
    def __init__(self):
        super(Ui_RenameWindow, self).__init__()
        self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint)  # 只显示关闭按钮
        self.setupUi(self) # 初始化窗体设置

    # 自动生成的代码,用来对窗体进行设置
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(507, 430)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        # 重命名设置区域
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(10, 10, 491, 141))
        self.groupBox.setObjectName("groupBox")
        # 文件名大写单选按钮
        self.radioButton = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton.setGeometry(QtCore.QRect(20, 30, 89, 16))
        self.radioButton.setChecked(True) # 默认选中
        self.radioButton.setObjectName("radioButton")
        # 文件名小写单选按钮
        self.radioButton_2 = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton_2.setGeometry(QtCore.QRect(130, 30, 89, 16))
        self.radioButton_2.setObjectName("radioButton_2")
        # 文件名编号单选按钮
        self.radioButton_3 = QtWidgets.QRadioButton(self.groupBox)
        self.radioButton_3.setGeometry(QtCore.QRect(20, 60, 89, 16))
        self.radioButton_3.setObjectName("radioButton_3")
        # 设置模板标签
        self.label = QtWidgets.QLabel(self.groupBox)
        self.label.setGeometry(QtCore.QRect(30, 90, 54, 21))
        self.label.setObjectName("label")
        # 起始编号标签
        self.label_2 = QtWidgets.QLabel(self.groupBox)
        self.label_2.setGeometry(QtCore.QRect(220, 90, 54, 21))
        self.label_2.setObjectName("label_2")
        # 设置起始编号的文本框
        self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_2.setGeometry(QtCore.QRect(280, 90, 61, 21))
        self.lineEdit_2.setObjectName("lineEdit_2")
        # 编号增量标签
        self.label_3 = QtWidgets.QLabel(self.groupBox)
        self.label_3.setGeometry(QtCore.QRect(360, 90, 54, 21))
        self.label_3.setObjectName("label_3")
        # 设置编号增量的文本框
        self.lineEdit_3 = QtWidgets.QLineEdit(self.groupBox)
        self.lineEdit_3.setGeometry(QtCore.QRect(420, 90, 61, 21))
        self.lineEdit_3.setObjectName("lineEdit_3")
        # 模板下拉列表
        self.comboBox = QtWidgets.QComboBox(self.groupBox)
        self.comboBox.setGeometry(QtCore.QRect(90, 90, 101, 22))
        self.comboBox.setObjectName("comboBox")
        # 模板中默认提供3种模板
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        # 图片设置区域
        self.groupBox_2 = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox_2.setGeometry(QtCore.QRect(10, 160, 491, 51))
        self.groupBox_2.setObjectName("groupBox_2")
        # 选择图片路径标签
        self.label_4 = QtWidgets.QLabel(self.groupBox_2)
        self.label_4.setGeometry(QtCore.QRect(30, 20, 91, 21))
        self.label_4.setObjectName("label_4")
        # 图片路径文本框
        self.lineEdit_4 = QtWidgets.QLineEdit(self.groupBox_2)
        self.lineEdit_4.setGeometry(QtCore.QRect(110, 20, 201, 21))
        self.lineEdit_4.setText("")
        self.lineEdit_4.setObjectName("lineEdit_4")
        # 选择按钮
        self.pushButton = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton.setGeometry(QtCore.QRect(320, 20, 75, 23))
        self.pushButton.setObjectName("pushButton")
        # 重命名按钮
        self.pushButton_2 = QtWidgets.QPushButton(self.groupBox_2)
        self.pushButton_2.setGeometry(QtCore.QRect(410, 20, 75, 23))
        self.pushButton_2.setObjectName("pushButton_2")
        # 显示图片及路径的表格
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setGeometry(QtCore.QRect(10, 210, 491, 191))
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(2) # 表格中添加两列
        self.tableWidget.setRowCount(0)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        self.tableWidget.setColumnWidth(0, 130)# 设置第一列宽度
        self.tableWidget.horizontalHeader().setStretchLastSection(True) # 设置自动填充容器
        self.tableWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)  # 垂直滚动条
        MainWindow.setCentralWidget(self.centralwidget)

        # 设置状态栏
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        self.statusbar.showMessage('准备就绪…… ')  # 设置状态栏默认值
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.comboBox.setCurrentIndex(0) # 模板下拉列表中默认选择第一项
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    # 自动生成的代码,用来设置窗体中控件的默认值
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "图片批量重命名"))
        self.groupBox.setTitle(_translate("MainWindow", "重命名设置"))
        self.radioButton.setText(_translate("MainWindow", "文件名大写"))
        self.radioButton_2.setText(_translate("MainWindow", "文件名小写"))
        self.radioButton_3.setText(_translate("MainWindow", "文件名编号"))
        self.label.setText(_translate("MainWindow", "设置模板:"))
        self.label_2.setText(_translate("MainWindow", "起始编号:"))
        self.lineEdit_2.setText(_translate("MainWindow", "1"))
        self.label_3.setText(_translate("MainWindow", "编号增量:"))
        self.lineEdit_3.setText(_translate("MainWindow", "1"))
        self.comboBox.setItemText(0, _translate("MainWindow", "img_***"))
        self.comboBox.setItemText(1, _translate("MainWindow", "fil_***"))
        self.comboBox.setItemText(2, _translate("MainWindow", "pic_***"))
        self.groupBox_2.setTitle(_translate("MainWindow", "图片设置"))
        self.label_4.setText(_translate("MainWindow", "选择图片路径:"))
        self.pushButton.setText(_translate("MainWindow", "选择"))
        self.pushButton_2.setText(_translate("MainWindow", "重命名"))
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(_translate("MainWindow", "图片名"))
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText(_translate("MainWindow", "图片路径"))
        # 关联“选择”按钮的方法,用来选择并显示图片列表
        self.pushButton.clicked.connect(self.getFiles)
        # 关联“重命名”按钮的方法,用来执行批量重命名操作
        self.pushButton_2.clicked.connect(self.reName)

    # 获取所有文件
    def getFiles(self):
        try:
            # 选择图片文件夹路径
            self.img_path = QFileDialog.getExistingDirectory(None, "选择图片文件夹路径", os.getcwd())
            self.lineEdit_4.setText(self.img_path) # 显示选择的图片路径
            self.list = os.listdir(self.img_path) # 遍历选择的文件夹
            num=0   # 记录图片数量
            self.tableWidget.setRowCount(0)   # 设置行数为0,以便清除所有行
            self.tableWidget.clearContents()   # 清除所有内容
            for i in range(0, len(self.list)): # 遍历图片列表
                filepath = os.path.join(self.img_path, self.list[i]) # 记录遍历到的文件名
                if os.path.isfile(filepath): # 判断是否为文件
                    imgType = os.path.splitext(filepath)[1]# 获取扩展名
                    if imageMark.Ui_MarkWindow().isImg(imgType): # 判断是否为图片
                        num += 1 # 数量加1
                        self.tableWidget.insertRow(i)  # 添加新行
                        # 设置第一列的值为文件名
                        self.tableWidget.setItem(i, 0, QtWidgets.QTableWidgetItem(self.list[i]))
                        # 设置第二列的值为文件路径
                        self.tableWidget.setItem(i, 1, QtWidgets.QTableWidgetItem(self.img_path))
            self.statusbar.showMessage('共有图片 '+str(num)+' 张')# 显示图片总数
        except Exception:
            QMessageBox.warning(None, '警告', '请选择一个有效路径……', QMessageBox.Ok)

    # 批量重命名
    def reName(self):
        num = 0  # 记录图片数量
        filename = "" # 记录原文件名
        newfilename = "" # 记录新文件名
        try:
            for i in range(self.tableWidget.rowCount()):  # 遍历图片列表
                filename = self.tableWidget.item(i,0).text()  # 记录遍历到的文件名
                filepath = os.path.join(self.img_path, filename)  # 记录遍历到的文件名(包括路径)
                if os.path.isfile(filepath):  # 判断是否为文件
                    imgType = os.path.splitext(filepath)[1]  # 获取扩展名
                    if imageMark.Ui_MarkWindow().isImg(imgType):  # 判断是否为图片
                        if self.radioButton.isChecked():  # 文件名大写
                            newfilename=str(filename).upper() # 将文件名转换为大写
                            newfilepath = os.path.join(self.img_path, newfilename)  # 新文件名(包括路径)
                            os.rename(filepath,newfilepath) # 重命名文件
                        elif self.radioButton_2.isChecked():  # 文件名小写
                            newfilename = str(filename).lower() # 将文件名转换为小写
                            newfilepath = os.path.join(self.img_path, newfilename)  # 新文件名(包括路径)
                            os.rename(filepath, newfilepath) # 重命名文件
                        elif self.radioButton_3.isChecked():  # 文件名编号
                            strid=self.comboBox.currentText() # 记录当前选择的模板
                            id=int(self.lineEdit_2.text())  # 记录开始编号
                            step=int(self.lineEdit_3.text()) # 记录增量值
                            template='{:0>3d}' # 设置编号格式化为3位
                            # 根据模板、起始编号和增量值生成新文件名
                            newfilename = strid[0:4]+template.format(id+step*i)+imgType
                            newfilepath = os.path.join(self.img_path, newfilename)   # 新文件名(包括路径)
                            os.rename(filepath, newfilepath) # 重命名文件
                        num += 1  # 数量加1
                        # 更新第一列的值为重命名之后的图片文件名
                        self.tableWidget.setItem(i, 0, QtWidgets.QTableWidgetItem(newfilename))
            self.statusbar.showMessage('批量重命名完成,共处理图片 ' + str(num) + ' 张')  # 状态栏中显示处理图片总数
        except Exception as e:
            print(e)
            QMessageBox.warning(None, '警告', '请选择正确的重命名方式!', QMessageBox.Ok)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值