Python+PyQt5开发一个图片尺寸修改器

 更新时间:2025年03月03日 14:10:44   作者:一晌小贪欢  
我们在日常办公时,经常需要将图片进行修改尺寸,本文将使用python和PyQt5开发一个方便图片修改尺寸工具,感兴趣的小伙伴可以了解一下

1、库的介绍

我们在日常办公时,经常需要将图片进行修改尺寸,比如上一些网址非常的不便捷,可以利用python+PyQt5写一个方便图片修改尺寸的代码

2、库的安装

用途安装
PyQt5界面设计pip install PyQt5 -i https://pypi.tuna.tsinghua.edu.cn/simple/
pillow图片处理pip install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple/

3、代码结构

1. init

  • 初始化窗口组件和变量。
  • 设置窗口标题、最小宽度,并调用 initUI 方法初始化用户界面。
  • 初始化一些状态变量,如 width_connected 和 height_connected(用于控制宽度和高度输入框之间的联动),以及图片路径和原始尺寸。

2. initUI

构建主窗口的布局和控件。

包括:

  • 文件选择区域(按钮和标签)。
  • 图片显示区域(支持拖放功能)。
  • 宽度和高度输入框。
  • 锁定比例复选框。
  • 保存按钮和状态标签。
  • 设置布局并初始化锁定比例功能。

3. dragEnterEvent

处理拖拽事件,判断是否允许文件拖放到图片显示区域。

如果拖拽的是文件,则接受该操作。

4. dropEvent

处理文件拖放到图片显示区域后的事件。

检查文件类型是否为图片(支持 .png, .jpg, .jpeg, .bmp),如果是,则加载图片。

5. loadImage

加载指定路径的图片。

使用 Pillow 库读取图片的原始尺寸,并更新预览图片。

初始化宽度和高度输入框的值为图片的原始尺寸。

启用保存按钮,并在状态标签中显示“图片已加载”。

6. selectImage

打开文件对话框,让用户选择图片文件。

如果用户选择了有效文件,则调用 loadImage 方法加载图片。

7. updatePreview

更新图片预览区域。

根据当前图片路径生成缩略图,并保持宽高比。

8. onLockAspectRatioChanged

处理锁定比例复选框的状态变化。

如果勾选了锁定比例:

连接宽度输入框和高度输入框的 textChanged 信号,实现两者联动。

如果取消勾选:

断开宽度和高度输入框的信号连接。

9. updateHeightFromWidth

当宽度输入框的值发生变化时,根据锁定比例计算并更新高度输入框的值。

防止递归调用导致死循环(通过临时断开高度输入框的信号连接)。

10. updateWidthFromHeight

当高度输入框的值发生变化时,根据锁定比例计算并更新宽度输入框的值。

同样防止递归调用导致死循环。

11. saveImage

保存调整后的图片。

获取用户输入的宽度和高度,检查其有效性。

使用 Pillow 库调整图片大小,并通过文件对话框选择保存路径。

如果保存成功,在状态标签中显示保存路径,并弹出提示框。

12. main

程序入口。

创建 QApplication 实例,初始化 ResizeImageTool 窗口,并进入主事件循环。

4、完整代码

# -*- coding: UTF-8 -*-
'''
@Project :测试 
@File    :test1.py
@IDE     :PyCharm 
@Author  :一晌小贪欢(278865463@qq.com)
@Date    :2025/3/1 21:07 
'''

import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QPushButton,
                             QLabel, QLineEdit, QFileDialog, QHBoxLayout,
                             QCheckBox, QMessageBox, QSpacerItem, QSizePolicy)
from PyQt5.QtGui import QPixmap, QIntValidator, QDragEnterEvent, QDropEvent
from PyQt5.QtCore import Qt
from PIL import Image


class ResizeImageTool(QWidget):
    def __init__(self):
        super().__init__()
        self.width_connected = False
        self.height_connected = False
        self.preview_size = 400  # 预览图片的最大尺寸
        self.initUI()

    def initUI(self):
        self.setWindowTitle('图片大小调整工具')
        self.setMinimumWidth(500)

        # 设置主布局
        self.layout = QVBoxLayout()
        self.layout.setSpacing(10)

        # 添加文件选择区域
        file_layout = QHBoxLayout()
        self.selectBtn = QPushButton('选择图片', self)
        self.selectBtn.clicked.connect(self.selectImage)
        self.filePathLabel = QLabel('未选择文件', self)
        file_layout.addWidget(self.selectBtn)
        file_layout.addWidget(self.filePathLabel)
        self.layout.addLayout(file_layout)

        # 显示图片的Label
        self.imageLabel = QLabel(self)
        self.imageLabel.setAlignment(Qt.AlignCenter)
        self.imageLabel.setMinimumHeight(self.preview_size)
        self.imageLabel.setAcceptDrops(True)  # 启用拖放功能
        self.imageLabel.dragEnterEvent = self.dragEnterEvent
        self.imageLabel.dropEvent = self.dropEvent
        self.layout.addWidget(self.imageLabel)

        # 设置尺寸输入区域
        size_layout = QHBoxLayout()

        # 宽度输入
        width_layout = QVBoxLayout()
        self.widthLabel = QLabel('宽度:', self)
        self.widthInput = QLineEdit(self)
        self.widthInput.setValidator(QIntValidator(1, 9999))
        width_layout.addWidget(self.widthLabel)
        width_layout.addWidget(self.widthInput)

        # 高度输入
        height_layout = QVBoxLayout()
        self.heightLabel = QLabel('高度:', self)
        self.heightInput = QLineEdit(self)
        self.heightInput.setValidator(QIntValidator(1, 9999))
        height_layout.addWidget(self.heightLabel)
        height_layout.addWidget(self.heightInput)

        size_layout.addLayout(width_layout)
        size_layout.addLayout(height_layout)
        self.layout.addLayout(size_layout)

        # 添加锁定比例复选框
        self.lockAspectRatioCheckBox = QCheckBox('锁定比例', self)
        self.lockAspectRatioCheckBox.setChecked(True)
        self.lockAspectRatioCheckBox.stateChanged.connect(self.onLockAspectRatioChanged)
        self.layout.addWidget(self.lockAspectRatioCheckBox)

        # 添加保存按钮
        self.saveBtn = QPushButton('保存调整后的图片', self)
        self.saveBtn.clicked.connect(self.saveImage)
        self.saveBtn.setEnabled(False)
        self.layout.addWidget(self.saveBtn)

        # 添加状态标签
        self.statusLabel = QLabel('', self)
        self.statusLabel.setAlignment(Qt.AlignCenter)
        self.layout.addWidget(self.statusLabel)

        # 设置主窗口的布局
        self.setLayout(self.layout)

        # 初始化变量
        self.imagePath = None
        self.originalWidth = None
        self.originalHeight = None

        # 初始状态下启用锁定比例
        self.onLockAspectRatioChanged(Qt.Checked)

    def dragEnterEvent(self, event: QDragEnterEvent):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()

    def dropEvent(self, event: QDropEvent):
        if event.mimeData().hasUrls():
            filePath = event.mimeData().urls()[0].toLocalFile()
            if filePath.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp')):
                self.loadImage(filePath)

    def loadImage(self, filePath):
        try:
            self.imagePath = filePath
            self.filePathLabel.setText(filePath)

            # 使用Pillow库读取图片原始尺寸
            img = Image.open(filePath)
            self.originalWidth, self.originalHeight = img.size

            # 更新预览图片
            self.updatePreview()

            # 初始化输入框
            self.widthInput.setText(str(self.originalWidth))
            self.heightInput.setText(str(self.originalHeight))

            # 启用保存按钮
            self.saveBtn.setEnabled(True)
            self.statusLabel.setText('图片已加载')

        except Exception as e:
            QMessageBox.critical(self, '错误', f'加载图片时出错:{str(e)}')

    def selectImage(self):
        filePath, _ = QFileDialog.getOpenFileName(
            self, '选择图片', '',
            'Images (*.png *.xpm *.jpg *.jpeg *.bmp)'
        )
        if filePath:
            self.loadImage(filePath)

    def updatePreview(self):
        if not self.imagePath:
            return

        pixmap = QPixmap(self.imagePath)
        scaled_pixmap = pixmap.scaled(
            self.preview_size,
            self.preview_size,
            Qt.KeepAspectRatio,
            Qt.SmoothTransformation
        )
        self.imageLabel.setPixmap(scaled_pixmap)

    def onLockAspectRatioChanged(self, state):
        if state == Qt.Checked:
            if not self.width_connected:
                self.widthInput.textChanged.connect(self.updateHeightFromWidth)
                self.width_connected = True
            if not self.height_connected:
                self.heightInput.textChanged.connect(self.updateWidthFromHeight)
                self.height_connected = True
        else:
            if self.width_connected:
                self.widthInput.textChanged.disconnect(self.updateHeightFromWidth)
                self.width_connected = False
            if self.height_connected:
                self.heightInput.textChanged.disconnect(self.updateWidthFromHeight)
                self.height_connected = False

    def updateHeightFromWidth(self):
        if not self.originalWidth or not self.originalHeight:
            return

        try:
            if self.height_connected:
                self.heightInput.textChanged.disconnect(self.updateWidthFromHeight)

            width = int(self.widthInput.text() or 0)
            if width > 0:
                height = int((self.originalHeight / self.originalWidth) * width)
                self.heightInput.setText(str(height))

            if self.height_connected:
                self.heightInput.textChanged.connect(self.updateWidthFromHeight)
        except ValueError:
            pass

    def updateWidthFromHeight(self):
        if not self.originalWidth or not self.originalHeight:
            return

        try:
            if self.width_connected:
                self.widthInput.textChanged.disconnect(self.updateHeightFromWidth)

            height = int(self.heightInput.text() or 0)
            if height > 0:
                width = int((self.originalWidth / self.originalHeight) * height)
                self.widthInput.setText(str(width))

            if self.width_connected:
                self.widthInput.textChanged.connect(self.updateHeightFromWidth)
        except ValueError:
            pass

    def saveImage(self):
        if not self.imagePath:
            return

        try:
            width = int(self.widthInput.text())
            height = int(self.heightInput.text())

            if width <= 0 or height <= 0:
                raise ValueError("尺寸必须大于0")

            img = Image.open(self.imagePath)
            img = img.resize((width, height), Image.Resampling.LANCZOS)

            savePath, _ = QFileDialog.getSaveFileName(
                self, '保存图片', '',
                'PNG (*.png);;JPEG (*.jpg *.jpeg);;BMP (*.bmp)'
            )

            if savePath:
                img.save(savePath)
                self.statusLabel.setText(f'图片已保存到: {savePath}')
                QMessageBox.information(self, '成功', '图片保存成功!')

        except ValueError as e:
            QMessageBox.warning(self, '警告', f"输入错误:{str(e)}")
        except Exception as e:
            QMessageBox.critical(self, '错误', f"保存失败:{str(e)}")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = ResizeImageTool()
    window.show()
    sys.exit(app.exec_())

效果如下

以上就是Python+PyQt5开发一个图片尺寸修改器的详细内容,更多关于Python图片尺寸修改的资料请关注脚本之家其它相关文章!

相关文章

  • 利用Python绘制酷炫的3D地图

    利用Python绘制酷炫的3D地图

    pyecharts是一款将python与echarts结合的强大的数据可视化工具。本文将为大家介绍如何利用pyecharts绘制酷炫的3D地图,感兴趣的小伙伴可以试一试
    2022-03-03
  • Python之集合详解

    Python之集合详解

    今天小编就为大家分享一篇关于Python中的集合介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2021-09-09
  • Python中glob.glob()函数的使用

    Python中glob.glob()函数的使用

    glob 模块用于查找规定路径下的文件路径名,本文主要介绍了Python中glob.glob()函数的使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • Python数据可视化之Pyecharts使用详解

    Python数据可视化之Pyecharts使用详解

    Pyecharts是一个由百度开源的、用于生成Echarts图表的类库,可以用来进行数据可视化分析。本文将详细讲解一下Pyecharts的使用,需要的可以参考一下
    2022-04-04
  • Python使用Selenium执行JavaScript代码的步骤详解

    Python使用Selenium执行JavaScript代码的步骤详解

    Selenium是一个用于自动化浏览器操作的工具,可以模拟人工操作,执行各种浏览器操作,而JavaScript是一种常用的脚本语言,本文将介绍如何在Python中使用Selenium执行JavaScript代码,并给出一些常见的应用示例
    2023-11-11
  • 使用Python+Appuim 清理微信的方法

    使用Python+Appuim 清理微信的方法

    这篇文章主要介绍了使用Python+Appuim 清理微信,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • Python编程二分法实现冒泡算法+快速排序代码示例

    Python编程二分法实现冒泡算法+快速排序代码示例

    这篇文章主要介绍了Python编程二分法实现冒泡算法+快速排序代码示例,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • Python实现检测文件的MD5值来查找重复文件案例

    Python实现检测文件的MD5值来查找重复文件案例

    这篇文章主要介绍了Python实现检测文件的MD5值来查找重复文件案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03
  • python 6行代码制作月历生成器

    python 6行代码制作月历生成器

    这篇文章主要介绍了python如何用6行代码制作月历生成器,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下
    2020-09-09
  • 在Django的视图(View)外使用Session的方法

    在Django的视图(View)外使用Session的方法

    这篇文章主要介绍了在Django的视图(View)外使用Session的方法,Django是最具人气的Python web开发框架,需要的朋友可以参考下
    2015-07-07

最新评论