<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在 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圖片檢視器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45