我正在使用 Python 和 QtDesigner 来显示带有叠加层的相机图像。 我的主窗口可以访问相机设置,并相应地触发相机。它通过 pyQtSlot 将每个图像发送到 QGraphicsView。
如何在此 QGraphicView 中启用缩放功能?
我已阅读答案如何在 QGraphicsView 中启用平移和缩放 它对于冻结的图片效果很好,但是当我发送下一张图像时,缩放会重置。
这是我的工作代码(因此我没有尝试实现缩放):
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QWidget, QGraphicsPixmapItem
from PyQt5.QtGui import QImage, QPainter, QPixmap
from PyQt5.QtCore import QRectF, pyqtSlot, Qt
class Display(QGraphicsView):
def __init__(self, parent: QWidget = None):
super().__init__(parent)
self._empty = True
self.image_qt = QImage()
self._scene = QGraphicsScene()
self.pic = QGraphicsPixmapItem()
self._scene.addItem(self.pic)
self.setScene(self._scene)
self.setAlignment(Qt.AlignCenter)
def hasPicture(self):
return not self._empty
@pyqtSlot(QImage)
def on_image_received(self, image: QImage, scale: float, x_offset: int, y_offset: int):
# Scale the overlay, Adjust the position
# self.image_qt = set_calque(image, scale, x_offset, y_offset)
# not useful for a minimal example, so skip the overlay part:
self.image_qt = image
# Image size
image_width = self.image_qt.width()
image_height = self.image_qt.height()
# Return if we don't have an image yet
if image_width == 0 or image_height == 0:
return
self._empty = False
self.pic.setPixmap(QPixmap.fromImage(self.image_qt))
self.fitInView(QRectF(0, 0, image_width, image_height), Qt.KeepAspectRatio)
self.update()
经过几次尝试,我几乎可以正常工作了:我认为缩放没有很好地集中在鼠标位置上,但我不明白为什么。
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QWidget, QGraphicsPixmapItem
from PyQt5.QtGui import QImage, QPainter, QPixmap
from PyQt5.QtCore import QRectF, pyqtSlot, Qt, QPoint
class Display(QGraphicsView):
def __init__(self, parent: QWidget = None):
super().__init__(parent)
self._zoom = 1
self._pt = QPoint()
self._empty = True
self.image_qt = QImage()
self._scene = QGraphicsScene()
self.pic = QGraphicsPixmapItem()
self._scene.addItem(self.pic)
self.setScene(self._scene)
self.setAlignment(Qt.AlignCenter)
def hasPicture(self):
return not self._empty
def wheelEvent(self, event):
# self.pt = self.mapToScene(event.pos()).toPoint()
self._pt = event.pos()
if self.hasPicture():
if event.angleDelta().y() > 0:
factor = 1.2
self._zoom *= factor
else:
factor = 0.8
self._zoom *= factor
if self._zoom > 0:
self.scale(factor, factor)
@pyqtSlot(QImage)
def on_image_received(self, image: QImage, scale: float, x_offset: int, y_offset: int):
# overlay the image. Scale the overlay, Adjust its position
self.image_qt = set_calque(image, scale, x_offset, y_offset)
# Image size
image_width = self.image_qt.width()
image_height = self.image_qt.height()
# Return if we don't have an image yet
if image_width == 0 or image_height == 0:
return
self._empty = False
self.setDragMode(QGraphicsView.ScrollHandDrag)
self.pic.setPixmap(QPixmap.fromImage(self.image_qt))
self.fitInView()
self.update()
def fitInView(self, scale=True):
rect = QRectF(self.pic.pixmap().rect())
if not rect.isNull():
if not self._pt.isNull() and self._zoom > 1:
rect.moveCenter(self._pt)
self.setSceneRect(rect)
if self.hasPicture():
unity = self.transform().mapRect(QRectF(0, 0, 1, 1))
self.scale(1 / unity.width(), 1 / unity.height())
viewrect = self.viewport().rect()
scenerect = self.transform().mapRect(rect)
factor = min(viewrect.width() / scenerect.width(),
viewrect.height() / scenerect.height())
factor *= self._zoom
self.scale(factor, factor)