PyQt5实现图片缩放、旋转

下面讲述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_()

实现效果:
在这里插入图片描述

  • 11
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kuokay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值