Python+PyQt5開(kāi)發(fā)一個(gè)圖片尺寸修改器
1、庫(kù)的介紹
我們?cè)谌粘^k公時(shí),經(jīng)常需要將圖片進(jìn)行修改尺寸,比如上一些網(wǎng)址非常的不便捷,可以利用python+PyQt5寫(xiě)一個(gè)方便圖片修改尺寸的代碼
2、庫(kù)的安裝
| 庫(kù) | 用途 | 安裝 |
|---|---|---|
| PyQt5 | 界面設(shè)計(jì) | pip install PyQt5 -i https://pypi.tuna.tsinghua.edu.cn/simple/ |
| pillow | 圖片處理 | pip install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple/ |
3、代碼結(jié)構(gòu)
1. init
- 初始化窗口組件和變量。
- 設(shè)置窗口標(biāo)題、最小寬度,并調(diào)用 initUI 方法初始化用戶(hù)界面。
- 初始化一些狀態(tài)變量,如 width_connected 和 height_connected(用于控制寬度和高度輸入框之間的聯(lián)動(dòng)),以及圖片路徑和原始尺寸。
2. initUI
構(gòu)建主窗口的布局和控件。
包括:
- 文件選擇區(qū)域(按鈕和標(biāo)簽)。
- 圖片顯示區(qū)域(支持拖放功能)。
- 寬度和高度輸入框。
- 鎖定比例復(fù)選框。
- 保存按鈕和狀態(tài)標(biāo)簽。
- 設(shè)置布局并初始化鎖定比例功能。
3. dragEnterEvent
處理拖拽事件,判斷是否允許文件拖放到圖片顯示區(qū)域。
如果拖拽的是文件,則接受該操作。
4. dropEvent
處理文件拖放到圖片顯示區(qū)域后的事件。
檢查文件類(lèi)型是否為圖片(支持 .png, .jpg, .jpeg, .bmp),如果是,則加載圖片。
5. loadImage
加載指定路徑的圖片。
使用 Pillow 庫(kù)讀取圖片的原始尺寸,并更新預(yù)覽圖片。
初始化寬度和高度輸入框的值為圖片的原始尺寸。
啟用保存按鈕,并在狀態(tài)標(biāo)簽中顯示“圖片已加載”。
6. selectImage
打開(kāi)文件對(duì)話(huà)框,讓用戶(hù)選擇圖片文件。
如果用戶(hù)選擇了有效文件,則調(diào)用 loadImage 方法加載圖片。
7. updatePreview
更新圖片預(yù)覽區(qū)域。
根據(jù)當(dāng)前圖片路徑生成縮略圖,并保持寬高比。
8. onLockAspectRatioChanged
處理鎖定比例復(fù)選框的狀態(tài)變化。
如果勾選了鎖定比例:
連接寬度輸入框和高度輸入框的 textChanged 信號(hào),實(shí)現(xiàn)兩者聯(lián)動(dòng)。
如果取消勾選:
斷開(kāi)寬度和高度輸入框的信號(hào)連接。
9. updateHeightFromWidth
當(dāng)寬度輸入框的值發(fā)生變化時(shí),根據(jù)鎖定比例計(jì)算并更新高度輸入框的值。
防止遞歸調(diào)用導(dǎo)致死循環(huán)(通過(guò)臨時(shí)斷開(kāi)高度輸入框的信號(hào)連接)。
10. updateWidthFromHeight
當(dāng)高度輸入框的值發(fā)生變化時(shí),根據(jù)鎖定比例計(jì)算并更新寬度輸入框的值。
同樣防止遞歸調(diào)用導(dǎo)致死循環(huán)。
11. saveImage
保存調(diào)整后的圖片。
獲取用戶(hù)輸入的寬度和高度,檢查其有效性。
使用 Pillow 庫(kù)調(diào)整圖片大小,并通過(guò)文件對(duì)話(huà)框選擇保存路徑。
如果保存成功,在狀態(tài)標(biāo)簽中顯示保存路徑,并彈出提示框。
12. main
程序入口。
創(chuàng)建 QApplication 實(shí)例,初始化 ResizeImageTool 窗口,并進(jìn)入主事件循環(huán)。
4、完整代碼
# -*- coding: UTF-8 -*-
'''
@Project :測(cè)試
@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 # 預(yù)覽圖片的最大尺寸
self.initUI()
def initUI(self):
self.setWindowTitle('圖片大小調(diào)整工具')
self.setMinimumWidth(500)
# 設(shè)置主布局
self.layout = QVBoxLayout()
self.layout.setSpacing(10)
# 添加文件選擇區(qū)域
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)
# 設(shè)置尺寸輸入?yún)^(qū)域
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)
# 添加鎖定比例復(fù)選框
self.lockAspectRatioCheckBox = QCheckBox('鎖定比例', self)
self.lockAspectRatioCheckBox.setChecked(True)
self.lockAspectRatioCheckBox.stateChanged.connect(self.onLockAspectRatioChanged)
self.layout.addWidget(self.lockAspectRatioCheckBox)
# 添加保存按鈕
self.saveBtn = QPushButton('保存調(diào)整后的圖片', self)
self.saveBtn.clicked.connect(self.saveImage)
self.saveBtn.setEnabled(False)
self.layout.addWidget(self.saveBtn)
# 添加狀態(tài)標(biāo)簽
self.statusLabel = QLabel('', self)
self.statusLabel.setAlignment(Qt.AlignCenter)
self.layout.addWidget(self.statusLabel)
# 設(shè)置主窗口的布局
self.setLayout(self.layout)
# 初始化變量
self.imagePath = None
self.originalWidth = None
self.originalHeight = None
# 初始狀態(tài)下啟用鎖定比例
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庫(kù)讀取圖片原始尺寸
img = Image.open(filePath)
self.originalWidth, self.originalHeight = img.size
# 更新預(yù)覽圖片
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, '錯(cuò)誤', f'加載圖片時(shí)出錯(cuò):{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"輸入錯(cuò)誤:{str(e)}")
except Exception as e:
QMessageBox.critical(self, '錯(cuò)誤', f"保存失?。簕str(e)}")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = ResizeImageTool()
window.show()
sys.exit(app.exec_())
效果如下

以上就是Python+PyQt5開(kāi)發(fā)一個(gè)圖片尺寸修改器的詳細(xì)內(nèi)容,更多關(guān)于Python圖片尺寸修改的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python常用request庫(kù)與lxml庫(kù)操作方法整理總結(jié)
一路學(xué)習(xí),一路總結(jié),技術(shù)就是這樣,應(yīng)用之后,在進(jìn)行整理,才可以加深印象。本篇文字為小節(jié)篇,核心總結(jié) requests 庫(kù)與 lxml 庫(kù)常用的操作2021-08-08
利用Python繪制隨機(jī)游走圖的詳細(xì)過(guò)程
隨機(jī)游走(random walk)也稱(chēng)隨機(jī)漫步,隨機(jī)行走等,是以隨機(jī)的方式采取連續(xù)步驟的過(guò)程,下面這篇文章主要給大家介紹了關(guān)于利用Python繪制隨機(jī)游走圖的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02
Python代碼使用 Pyftpdlib實(shí)現(xiàn)FTP服務(wù)器功能
FTP 服務(wù)器,在此之前我都是使用Linux的vsftpd軟件包來(lái)搭建FTP服務(wù)器的,現(xiàn)在發(fā)現(xiàn)了利用pyftpdlib可以更加簡(jiǎn)單的方法即可實(shí)現(xiàn)FTP服務(wù)器的功能 ,需要的朋友可以參考下2019-07-07
Conda國(guó)內(nèi)鏡像源及配置過(guò)程
文章介紹Conda鏡像源使用方法,涵蓋臨時(shí)指定單個(gè)/多個(gè)源、永久配置及恢復(fù)默認(rèn)設(shè)置,同時(shí)說(shuō)明main(官方穩(wěn)定)、free(逐漸棄用)、conda-forge(社區(qū)更新快)等倉(cāng)庫(kù)的區(qū)別與適用場(chǎng)景2025-08-08
Python實(shí)現(xiàn)截取PDF文件中的幾頁(yè)代碼實(shí)例
今天小編就為大家分享一篇關(guān)于Python實(shí)現(xiàn)截取PDF文件中的幾頁(yè)代碼實(shí)例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03
在 Django/Flask 開(kāi)發(fā)服務(wù)器上使用 HTTPS
使用 Django 或 Flask 這種框架開(kāi)發(fā) web app 的時(shí)候一般都會(huì)用內(nèi)建服務(wù)器開(kāi)發(fā)和調(diào)試程序,等程序完成后再移交到生產(chǎn)環(huán)境部署。問(wèn)題是這些內(nèi)建服務(wù)器通常都不支持 HTTPS,那么我們來(lái)探討下開(kāi)啟https吧2014-07-07

