|
| 1 | +#!/usr/bin/env python |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | + |
| 4 | +""" |
| 5 | +Created on 2020/11/12 |
| 6 | +@author: Irony |
| 7 | +@site: https://github.com/892768447 |
| 8 | + |
| 9 | +@file: ImageView |
| 10 | +@description: 图片查看控件,支持移动、放大、缩小 |
| 11 | +""" |
| 12 | + |
| 13 | +__Author__ = 'Irony' |
| 14 | +__Copyright__ = 'Copyright (c) 2020 Irony' |
| 15 | +__Version__ = 1.0 |
| 16 | + |
| 17 | +import os |
| 18 | + |
| 19 | +from PyQt5.QtCore import QPoint, QPointF, Qt |
| 20 | +from PyQt5.QtGui import QPainter, QColor, QImage, QPixmap |
| 21 | +from PyQt5.QtWidgets import QWidget |
| 22 | + |
| 23 | + |
| 24 | +class ImageView(QWidget): |
| 25 | + """图片查看控件""" |
| 26 | + |
| 27 | + def __init__(self, image, *args, **kwargs): |
| 28 | + super(ImageView, self).__init__(*args, **kwargs) |
| 29 | + self.setCursor(Qt.OpenHandCursor) |
| 30 | + self._image = None |
| 31 | + self._pos = QPoint(0, 0) # 移动图片偏移 |
| 32 | + self._p_pos = None # 鼠标按下点 |
| 33 | + self._scale = 1 # 缩放 |
| 34 | + self._max_scale = 20 # 最大放大级别 |
| 35 | + self._background = kwargs.pop('background', None) |
| 36 | + self.setPixmap(image) |
| 37 | + |
| 38 | + def setMaxScale(self, scale): |
| 39 | + """设置最大放大级别,默认为20 |
| 40 | + :param scale: 最大缩放 |
| 41 | + :type scale: int |
| 42 | + """ |
| 43 | + self._max_scale = scale |
| 44 | + |
| 45 | + def setBackground(self, color): |
| 46 | + """设置背景颜色 |
| 47 | + :param color: 背景颜色 |
| 48 | + :type color: QColor or str |
| 49 | + """ |
| 50 | + if isinstance(color, QColor): |
| 51 | + self._background = color |
| 52 | + elif isinstance(color, str): |
| 53 | + color = QColor(color) |
| 54 | + if color.isValid(): |
| 55 | + self._background = color |
| 56 | + else: |
| 57 | + return |
| 58 | + self.update() |
| 59 | + |
| 60 | + def setPixmap(self, image): |
| 61 | + """加载图片 |
| 62 | + :param image: 图片或者图片路径 |
| 63 | + :type image: QPixmap or QImage or str |
| 64 | + """ |
| 65 | + if isinstance(image, QPixmap): |
| 66 | + self._image = image |
| 67 | + elif isinstance(image, QImage): |
| 68 | + self._image = QPixmap.fromImage(image) |
| 69 | + elif isinstance(image, str) and os.path.isfile(image): |
| 70 | + self._image = QPixmap(image) |
| 71 | + else: |
| 72 | + return |
| 73 | + self._pos = QPoint(0, 0) |
| 74 | + self._p_pos = None |
| 75 | + self.update() |
| 76 | + |
| 77 | + def mousePressEvent(self, event): |
| 78 | + """鼠标按下修改鼠标样式以及记录初始移动点""" |
| 79 | + super(ImageView, self).mousePressEvent(event) |
| 80 | + self.setCursor(Qt.ClosedHandCursor) |
| 81 | + if event.button() == Qt.LeftButton: |
| 82 | + self._p_pos = event.pos() |
| 83 | + |
| 84 | + def mouseReleaseEvent(self, event): |
| 85 | + """鼠标释放修改鼠标样式""" |
| 86 | + super(ImageView, self).mouseReleaseEvent(event) |
| 87 | + self.setCursor(Qt.OpenHandCursor) |
| 88 | + self._p_pos = None |
| 89 | + |
| 90 | + def mouseMoveEvent(self, event): |
| 91 | + """鼠标移动图片""" |
| 92 | + super(ImageView, self).mouseMoveEvent(event) |
| 93 | + if event.buttons() == Qt.LeftButton and self._p_pos: |
| 94 | + offset = event.pos() - self._p_pos |
| 95 | + self._p_pos += offset |
| 96 | + self._pos += offset |
| 97 | + self.update() |
| 98 | + |
| 99 | + def wheelEvent(self, event): |
| 100 | + super(ImageView, self).wheelEvent(event) |
| 101 | + step = 0.4 if self._scale > 1.1 else 0.1 |
| 102 | + if event.angleDelta().y() > 0: |
| 103 | + # 放大 |
| 104 | + self._scale += step |
| 105 | + self._scale = min(self._scale, self._max_scale) |
| 106 | + else: |
| 107 | + # 缩小 |
| 108 | + self._scale -= step |
| 109 | + self._scale = max(self._scale, 0.1) |
| 110 | + self.update() |
| 111 | + |
| 112 | + def paintEvent(self, event): |
| 113 | + super(ImageView, self).paintEvent(event) |
| 114 | + painter = QPainter(self) |
| 115 | + painter.setRenderHint(QPainter.Antialiasing) |
| 116 | + painter.setRenderHint(QPainter.SmoothPixmapTransform) |
| 117 | + if self._background: |
| 118 | + painter.fillRect(self.rect(), self._background) |
| 119 | + if not self._image or self._image.isNull(): |
| 120 | + return |
| 121 | + # 变换坐标中心为窗口中点 |
| 122 | + painter.translate(self.width() / 2, self.height() / 2) |
| 123 | + # 缩放 |
| 124 | + painter.scale(self._scale, self._scale) |
| 125 | + painter.drawPixmap(QPointF(-self._image.width() / 2 + self._pos.x(), -self._image.height() / 2 + self._pos.y()), |
| 126 | + self._image) |
| 127 | + |
| 128 | + |
| 129 | +if __name__ == '__main__': |
| 130 | + import sys |
| 131 | + import cgitb |
| 132 | + |
| 133 | + cgitb.enable(format='text') |
| 134 | + from PyQt5.QtWidgets import QApplication |
| 135 | + |
| 136 | + app = QApplication(sys.argv) |
| 137 | + w = ImageView('ScreenShot/CallVirtualKeyboard2.png') |
| 138 | + w.show() |
| 139 | + sys.exit(app.exec_()) |
0 commit comments