Python+PyQt5制作一个图片查看器
目录
前言实现方式测试前言
在 PyQt 中可以使用很多方式实现照片查看器,最朴素的做法就是重写QWidget
的paintEvent()
、mouseMoveEvent
等事件,但是如果要在图像上多添加一些形状,那么在对图像进行缩放旋转等仿射变换时需要对这些形状也这些变换,虽然不难,但是从头实现这些变换还有形状还是挺讨厌的。好在 Qt 提供了图形视图框架,关于这个框架的基本使用可以参见深入了解PyQt5中的图形视图框架,下面进入正题。
实现方式
一个最基本的照片查看器应该具有以下功能:
载入图像缩放图像在窗口尺寸小于图像时允许拖拽图像载入图像可以使用QGraphicsPixmapItem
来解决,缩放图像使用QGraphicsView
的scale(sx, sy)
解决,移动图像只需将QGraphicsView
的dragMode
设置为QGraphicsView.ScrollHandDrag
即可。因为常常使用鼠标滚轮来缩放图像,所以还需要重写重写以下QGraphicsView
的wheelEvent
。
实际上由于窗口的缩放导致视口大小变化,还有一些细枝末节需要处理。具体代码如下:
# coding:utf-8 import sys from PyQt5.QtCore import QRect, QRectF, QSize, Qt from PyQt5.QtGui import QPainter, QPixmap, QWheelEvent from PyQt5.QtWidgets import (QApplication, QGraphicsItem, QGraphicsPixmapItem, QGraphicsScene, QGraphicsView) class ImageViewer(QGraphicsView): """ 图片查看器 """ def __init__(self, parent=None): super().__init__(parent=parent) self.zoomInTimes = 0 self.maxZoomInTimes = 22 # 创建场景 self.graphicsScene = QGraphicsScene() # 图片 self.pixmap = QPixmap(r"D:\hzz\图片\硝子\硝子 (2).jpg") self.pixmapItem = QGraphicsPixmapItem(self.pixmap) self.displayedImageSize = QSize(0, 0) # 初始化小部件 self.__initWidget() def __initWidget(self): """ 初始化小部件 """ self.resize(1200, 900) # 隐藏滚动条 self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 以鼠标所在位置为锚点进行缩放 self.setTransformationAnchor(self.AnchorUnderMouse) # 平滑缩放 self.pixmapItem.setTransformationMode(Qt.SmoothTransformation) self.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) # 设置场景 self.graphicsScene.addItem(self.pixmapItem) self.setScene(self.graphicsScene) def wheelEvent(self, e: QWheelEvent): """ 滚动鼠标滚轮缩放图片 """ if e.angleDelta().y() > 0: self.zoomIn() else: self.zoomOut() def resizeEvent(self, e): """ 缩放图片 """ super().resizeEvent(e) if self.zoomInTimes > 0: return # 调整图片大小 ratio = self.__getScaleRatio() self.displayedImageSize = self.pixmap.size()*ratio if ratio < 1: self.fitInView(self.pixmapItem, Qt.KeepAspectRatio) else: self.resetTransform() def setImage(self, imagePath: str): """ 设置显示的图片 """ self.resetTransform() # 刷新图片 self.pixmap = QPixmap(imagePath) self.pixmapItem.setPixmap(self.pixmap) # 调整图片大小 self.setSceneRect(QRectF(self.pixmap.rect())) ratio = self.__getScaleRatio() self.displayedImageSize = self.pixmap.size()*ratio if ratio < 1: self.fitInView(self.pixmapItem, Qt.KeepAspectRatio) def resetTransform(self): """ 重置变换 """ super().resetTransform() self.zoomInTimes = 0 self.__setDragEnabled(False) def __isEnableDrag(self): """ 根据图片的尺寸决定是否启动拖拽功能 """ v = self.verticalScrollBar().maximum() > 0 h = self.horizontalScrollBar().maximum() > 0 return v or h def __setDragEnabled(self, isEnabled: bool): """ 设置拖拽是否启动 """ self.setDragMode( self.ScrollHandDrag if isEnabled else self.NoDrag) def __getScaleRatio(self): """ 获取显示的图像和原始图像的缩放比例 """ if self.pixmap.isNull(): return 1 pw = self.pixmap.width() ph = self.pixmap.height() rw = min(1, self.width()/pw) rh = min(1, self.height()/ph) return min(rw, rh) def fitInView(self, item: QGraphicsItem, mode=Qt.KeepAspectRatio): """ 缩放场景使其适应窗口大小 """ super().fitInView(item, mode) self.displayedImageSize = self.__getScaleRatio()*self.pixmap.size() self.zoomInTimes = 0 def zoomIn(self, viewAnchor=QGraphicsView.AnchorUnderMouse): """ 放大图像 """ if self.zoomInTimes == self.maxZoomInTimes: return self.setTransformationAnchor(viewAnchor) self.zoomInTimes += 1 self.scale(1.1, 1.1) self.__setDragEnabled(self.__isEnableDrag()) # 还原 anchor self.setTransformationAnchor(self.AnchorUnderMouse) def zoomOut(self, viewAnchor=QGraphicsView.AnchorUnderMouse): """ 缩小图像 """ if self.zoomInTimes == 0 and not self.__isEnableDrag(): return self.setTransformationAnchor(viewAnchor) self.zoomInTimes -= 1 # 原始图像的大小 pw = self.pixmap.width() ph = self.pixmap.height() # 实际显示的图像宽度 w = self.displayedImageSize.width()*1.1**self.zoomInTimes h = self.displayedImageSize.height()*1.1**self.zoomInTimes if pw > self.width() or ph > self.height(): # 在窗口尺寸小于原始图像时禁止继续缩小图像比窗口还小 if w <= self.width() and h <= self.height(): self.fitInView(self.pixmapItem) else: self.scale(1/1.1, 1/1.1) else: # 在窗口尺寸大于图像时不允许缩小的比原始图像小 if w <= pw: self.resetTransform() else: self.scale(1/1.1, 1/1.1) self.__setDragEnabled(self.__isEnableDrag()) # 还原 anchor self.setTransformationAnchor(self.AnchorUnderMouse) if __name__ == "__main__": app = QApplication(sys.argv) w = ImageViewer() w.show() sys.exit(app.exec_())
测试
来看一下实际的使用效果:
到此这篇关于Python+PyQt5制作一个图片查看器的文章就介绍到这了,更多相关PyQt5图片查看器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
X 关闭
X 关闭
- 15G资费不大降!三大运营商谁提供的5G网速最快?中国信通院给出答案
- 2联想拯救者Y70发布最新预告:售价2970元起 迄今最便宜的骁龙8+旗舰
- 3亚马逊开始大规模推广掌纹支付技术 顾客可使用“挥手付”结账
- 4现代和起亚上半年出口20万辆新能源汽车同比增长30.6%
- 5如何让居民5分钟使用到各种设施?沙特“线性城市”来了
- 6AMD实现连续8个季度的增长 季度营收首次突破60亿美元利润更是翻倍
- 7转转集团发布2022年二季度手机行情报告:二手市场“飘香”
- 8充电宝100Wh等于多少毫安?铁路旅客禁止、限制携带和托运物品目录
- 9好消息!京东与腾讯续签三年战略合作协议 加强技术创新与供应链服务
- 10名创优品拟通过香港IPO全球发售4100万股 全球发售所得款项有什么用处?