下面讲述PyQt5实现图片缩放、旋转的两种方式
pyqt5实现过程如下
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QWidget
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
'''定义主窗口'''
class myWindow(QWidget): # 不可用QMainWindow,因为QLabel继承自QWidget
def __init__(self):
super(myWindow, self).__init__()
self.resize(500,500) # 设定窗口大小(根据自己显示图片的大小,可更改)
self.setWindowTitle("图片操作") # 设定窗口名称
self.imgPixmap = QPixmap('image/cc4.png') # 载入图片
self.scaledImg = self.imgPixmap.scaled(self.size()) # 初始化缩放图
self.singleOffset = QPoint(0, 0) # 初始化偏移值
self.isLeftPressed = bool(False) # 图片被点住(鼠标左键)标志位
self.isImgLabelArea = bool(True) # 鼠标进入label图片显示区域
'''重载绘图: 动态绘图'''
def paintEvent(self,event):
self.imgPainter = QPainter() # 用于动态绘制图片
self.imgFramePainter = QPainter() # 用于动态绘制图片外线框
self.imgPainter.begin(self) # 无begin和end,则将一直循环更新
self.imgPainter.drawPixmap(self.singleOffset, self.scaledImg) # 从图像文件提取Pixmap并显示在指定位置
self.imgFramePainter.setPen(QColor(168, 34, 3)) # 不设置则为默认黑色 # 设置绘图颜色/大小/样式
self.imgFramePainter.drawRect(10, 10, 480, 480) # 为图片绘外线狂(向外延展1)
self.imgPainter.end() # 无begin和end,则将一直循环更新
# =============================================================================
# 图片移动: 首先,确定图片被点选(鼠标左键按下)且未左键释放;
# 其次,确定鼠标移动;
# 最后,更新偏移值,移动图片.
# =============================================================================
'''重载一下鼠标按下事件(单击)'''
def mousePressEvent(self, event):
if event.buttons() == QtCore.Qt.LeftButton: # 左键按下
print("鼠标左键单击") # 响应测试语句
self.isLeftPressed = True; # 左键按下(图片被点住),置Ture
self.preMousePosition = event.pos() # 获取鼠标当前位置
elif event.buttons () == QtCore.Qt.RightButton: # 右键按下
print("鼠标右键单击") # 响应测试语句
elif event.buttons() == QtCore.Qt.MidButton: # 中键按下
print("鼠标中键单击") # 响应测试语句
elif event.buttons() == QtCore.Qt.LeftButton | QtCore.Qt.RightButton: # 左右键同时按下
print("鼠标左右键同时单击") # 响应测试语句
elif event.buttons() == QtCore.Qt.LeftButton | QtCore.Qt.MidButton: # 左中键同时按下
print("鼠标左中键同时单击") # 响应测试语句
elif event.buttons() == QtCore.Qt.MidButton | QtCore.Qt.RightButton: # 右中键同时按下
print("鼠标右中键同时单击") # 响应测试语句
elif event.buttons() == QtCore.Qt.LeftButton | QtCore.Qt.MidButton \
| QtCore.Qt.RightButton: # 左中右键同时按下
print("鼠标左中右键同时单击") # 响应测试语句
'''重载一下滚轮滚动事件'''
def wheelEvent(self, event):
# if event.delta() > 0: # 滚轮上滚,PyQt4
# This function has been deprecated, use pixelDelta() or angleDelta() instead.
angle=event.angleDelta() / 8 # 返回QPoint对象,为滚轮转过的数值,单位为1/8度
angleX=angle.x() # 水平滚过的距离(此处用不上)
angleY=angle.y() # 竖直滚过的距离
if angleY > 0: # 滚轮上滚
print("鼠标中键上滚") # 响应测试语句
self.scaledImg = self.imgPixmap.scaled(self.scaledImg.width()+5,
self.scaledImg.height()+5)
newWidth = event.x() - (self.scaledImg.width() * (event.x()-self.singleOffset.x())) \
/ (self.scaledImg.width()-5)
newHeight = event.y() - (self.scaledImg.height() * (event.y()-self.singleOffset.y())) \
/ (self.scaledImg.height()-5)
self.singleOffset = QPoint(newWidth, newHeight) # 更新偏移量
self.repaint() # 重绘
else: # 滚轮下滚
print("鼠标中键下滚") # 响应测试语句
self.scaledImg = self.imgPixmap.scaled(self.scaledImg.width()-5,
self.scaledImg.height()-5)
newWidth = event.x() - (self.scaledImg.width() * (event.x()-self.singleOffset.x())) \
/ (self.scaledImg.width()+5)
newHeight = event.y() - (self.scaledImg.height() * (event.y()-self.singleOffset.y())) \
/ (self.scaledImg.height()+5)
self.singleOffset = QPoint(newWidth, newHeight) # 更新偏移量
self.repaint() # 重绘
'''重载一下鼠标键公开事件'''
def mouseReleaseEvent(self, event):
if event.buttons() == QtCore.Qt.LeftButton: # 左键释放
self.isLeftPressed = False; # 左键释放(图片被点住),置False
print("鼠标左键松开") # 响应测试语句
elif event.button() == Qt.RightButton: # 右键释放
self.singleOffset = QPoint(0, 0) # 置为初值
self.scaledImg = self.imgPixmap.scaled(self.size()) # 置为初值
self.repaint() # 重绘
print("鼠标右键松开") # 响应测试语句
'''重载一下鼠标移动事件'''
def mouseMoveEvent(self,event):
if self.isLeftPressed: # 左键按下
print("鼠标左键按下,移动鼠标") # 响应测试语句
self.endMousePosition = event.pos() - self.preMousePosition # 鼠标当前位置-先前位置=单次偏移量
self.singleOffset = self.singleOffset + self.endMousePosition # 更新偏移量
self.preMousePosition = event.pos() # 更新当前鼠标在窗口上的位置,下次移动用
self.repaint() # 重绘
# '''重载一下鼠标双击事件'''
# def mouseDoubieCiickEvent(self, event):
# if event.buttons() == QtCore.Qt.LeftButton: # 左键按下
# self.setText ("双击鼠标左键的功能: 自己定义")
#
#
# '''重载一下鼠标进入控件事件'''
# def enterEvent(self, event):
#
#
# '''重载一下鼠标离开控件事件'''
# def leaveEvent(self, event):
#
# '''重载一下鼠标进入控件事件'''
# def enterEvent(self, event):
#
#
# '''重载一下鼠标离开控件事件'''
# def leaveEvent(self, event):
#
'''主函数'''
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
myshow = myWindow()
myshow.show()
sys.exit (app.exec_())
实现效果:
# -*- coding: utf-8 -*-
"""
Created on Tue Apr 26 19:33:16 2019
@author: Tiny
"""
# =============================================================================
''' 采用PyQt5实现,基本功能如下:
1. 图片缩放(点选/快捷键两种方式,单次缩放尺度小伙伴们自己可调);
2. 图片旋转(点选/快捷键两种方式,单次旋转角度小伙伴们自己可调);
3. 图片移动(点选/快捷键两种方式,单次移动距离小伙伴们自己可调)-->待开发,后续续上。'''
# =============================================================================
# =============================================================================
''' 该代码存在一个问题:'''
# 图片缩小很小时,长宽比例保持的不好,且再次放大后,图片失真,图片信息丢掉很多!
''' 内存中存放原图,针对原图设定一个缩放ratio变量,在原图基础上做缩放'''
# =============================================================================
# =============================================================================
''' 注意:'''
# 1. self.imageLabel.setScaledContents(True) #允许QLabel缩放它的内容充满整个可用的空间。
# 小伙伴可以看一下设置不设置该局的图片显示区别;
# 2. 注意一下PyQt4和PyQt5的个别函数用法的区别;
# 3. 很多函数类似,完全可以编写为一个函数,不需要那么多行代码,都是重复的;
# 4. 在别人的基础上改的,玩玩,大家可做个参考。
# =============================================================================
# =============================================================================
''' PyQt5 与PyQt4 的一些区别,供小伙伴们参考:'''
# 需用QtWidgets.QLabel(), # PyQt4
# 不是QLabel(); # PyQt5
#
# 需用QtWidgets.QAction(QIcon, QString, QObject), # PyQt4
# 不是QAction(QIcon, QString, QObject); # PyQt5
#
# The old style:
# self.connect(origin, SIGNAL('completed'), self._show_results) # PyQt4
# should now be written in the new style:
# origin.completed.connect(self._show_results) # PyQt5
#
# PyQt5中已经不再支持PyQt4种不推荐方法 QMatrix
# 可通过QTransform 实现
# =============================================================================
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
from PyQt5.QtWidgets import QMainWindow , QApplication
from PyQt5 import QtWidgets # , QtCore, QtGui
'''定义主窗口(包含菜单栏、工具栏)'''
class MainWindow(QMainWindow):
def __init__(self,parent=None):
super(MainWindow,self).__init__(parent)
f=QFont("ZYSong18030",12) # 设置字体,字号
self.setFont(f)
self.setWindowTitle("Image Processor") # 窗口命名
self.imageLabel=QtWidgets.QLabel() # 需用QtWidgets.QLabel(),不是QLabel()
# self.imageLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
self.imageLabel.setScaledContents(True) #允许QLabel缩放它的内容充满整个可用的空间
self.setCentralWidget(self.imageLabel) # 注释掉该句,则运行不会显示图片
self.image=QImage()
if self.image.load("image/cc.png"): # 如果载入图片,则
self.imageLabel.setPixmap(QPixmap.fromImage(self.image)) # 显示图片
self.resize(self.image.width(),self.image.height()) # 重设大小
self.createActions() # 创建“放大”、“缩小”及“旋转”等的QAction
self.createMenus() # 创建菜单栏
self.createToolBars() # 创建工具栏
'''创建缩放、旋转的QAction'''
def createActions(self):
self.zoomInAction=QtWidgets.QAction(QIcon("image/zoomIn.gif"),
self.tr("放大"),self) # 不是QAction(QIcon, QString, QObject)
self.zoomInAction.setShortcut("Ctrl+I") # 设置快捷键
self.zoomInAction.setStatusTip(self.tr("放大")) # 设置标题栏
# self.connect(self.zoomInAction,SIGNAL("triggered()"),
# self.slotZoomin) # PyQt4
self.zoomInAction.triggered.connect(self.slotZoomIn) # PyQt5
self.zoomOutAction=QtWidgets.QAction(QIcon("image/zoomOut.gif"),
self.tr("缩小"),self) # 不是QAction(QIcon, QString, QObject)
self.zoomOutAction.setShortcut("Ctrl+O") # 设置快捷键
self.zoomOutAction.setStatusTip(self.tr("缩小")) # 设置标题栏
# self.connect(self.zoomOutAction,SIGNAL("triggered()"),
# self.slotZoomOut) # PyQt4
self.zoomOutAction.triggered.connect(self.slotZoomOut) # PyQt5
self.rotateAction=QtWidgets.QAction(QIcon("image/rotate.gif"),
self.tr("顺旋"),self) # 不是QAction(QIcon, QString, QObject)
self.rotateAction.setShortcut("Ctrl+R") # 设置快捷键
self.rotateAction.setStatusTip(self.tr("顺旋")) # 设置标题栏
# self.connect(self.rotateAction,SIGNAL("triggered()"),
# self.slotRotate) # PyQt4
self.rotateAction.triggered.connect(self.slotRotate) # PyQt5
self.rotateAntiAction=QtWidgets.QAction(QIcon("image/rotateAnti.gif"),
self.tr("逆旋"),self) # 不是QAction(QIcon, QString, QObject)
self.rotateAntiAction.setShortcut("Ctrl+E") # 设置快捷键
self.rotateAntiAction.setStatusTip(self.tr("逆旋")) # 设置标题栏
# self.connect(self.rotateAntiAction,SIGNAL("triggered()"),
# self.slotRotateAnti) # PyQt4
self.rotateAntiAction.triggered.connect(self.slotRotateAnti) # PyQt5
'''创建菜单栏'''
def createMenus(self):
zoomMenu=self.menuBar().addMenu(self.tr("缩放")) # 缩放菜单选项
zoomMenu.addAction(self.zoomInAction) # 放大子选项
zoomMenu.addAction(self.zoomOutAction) # 缩小子选项
rotateMenu=self.menuBar().addMenu(self.tr("旋转")) # 旋转菜单选项
rotateMenu.addAction(self.rotateAction) # 顺旋子选项
rotateMenu.addAction(self.rotateAntiAction) # 逆旋子选项
'''创建工具栏'''
def createToolBars(self):
fileToolBar=self.addToolBar("Print")
fileToolBar.addAction(self.zoomInAction)
fileToolBar.addAction(self.zoomOutAction)
fileToolBar.addAction(self.rotateAntiAction)
fileToolBar.addAction(self.rotateAction)
'''图片放大(倍数可设)'''
def slotZoomIn(self):
if self.image.isNull(): # 没图片,则不执行任何操作
return
# martix =QMatrix() # PyQt4,PyQt5中已废弃
transform = QTransform() # PyQt5
# martix.scale(2,2) # PyQt4,PyQt5中已废弃
transform.scale(1.2,1.2) # PyQt5
self.image=self.image.transformed(transform); # 相应的matrix改为transform
self.imageLabel.setPixmap(QPixmap.fromImage(self.image)) # 显示图片到Qlabel控件
self.resize(self.image.width(),self.image.height())
'''图片缩小(倍数可设)'''
def slotZoomOut(self):
if self.image.isNull(): # 没图片,则不执行任何操作
return
# martix =QMatrix() # PyQt4,PyQt5中已废弃
transform = QTransform() # PyQt5
# martix.scale(2,2) # PyQt4,PyQt5中已废弃
transform.scale(0.8,0.8) # PyQt5
self.image=self.image.transformed(transform); # 相应的matrix改为transform
self.imageLabel.setPixmap(QPixmap.fromImage(self.image)) # 显示图片到Qlabel控件
self.resize(self.image.width(),self.image.height())
'''图片顺旋(角度可设)'''
def slotRotate(self):
if self.image.isNull(): # 没图片,则不执行任何操作
return
# martix =QMatrix() # PyQt4,PyQt5中已废弃
transform = QTransform() # PyQt5
# martix.rotate(90) # PyQt4,PyQt5中已废弃
transform.rotate(90) # PyQt5
self.image=self.image.transformed(transform); # 相应的matrix改为transform
self.imageLabel.setPixmap(QPixmap.fromImage(self.image)) # 显示图片到Qlabel控件
self.resize(self.image.width(),self.image.height())
'''图片逆旋(角度可设)'''
def slotRotateAnti(self):
if self.image.isNull(): # 没图片,则不执行任何操作
return
# martix =QMatrix() # PyQt4,PyQt5中已废弃
transform = QTransform() # PyQt5
# martix.rotate(90) # PyQt4,PyQt5中已废弃
transform.rotate(-90) # PyQt5
self.image=self.image.transformed(transform); # 相应的matrix改为transform
self.imageLabel.setPixmap(QPixmap.fromImage(self.image)) # 显示图片到Qlabel控件
self.resize(self.image.width(),self.image.height())
'''主函数'''
if __name__ == '__main__':
app=QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec_()