[Python] Zooming and Panning with Pinch and Swipe gesture in a QGraphicsView with PyQt5 on Mac...

Discussão em 'Python' iniciado por Stack, Novembro 28, 2025.

  1. Stack

    Stack Membro Participativo

    I need to implement a zooming for a QGraphicsView on a pinch gesture (with 2 fingers) and panning along the scene with a swipe gesture (also with 2 fingers) in PyQt5.15.7 on Windows and Mac (and optimaly working for Linux aswell). I tried to achieve this with the following code:

    import sys

    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *

    class View(QGraphicsView):
    def __init__(self, parent=None):
    super().__init__(parent)

    self.zoom_in_factor = 1.25
    self.zoom = 10
    self.zoom_step = 1
    self.zoom_clamp = True
    self.zoom_range = [1, 10]
    self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)

    self.scene = QGraphicsScene()
    self.scene.setSceneRect(-5000, -5000, 10000, 10000)
    self.scene.addRect(0, 0, 100, 100, QPen(Qt.NoPen), QBrush(Qt.green))

    self.setScene(self.scene)

    def wheelEvent(self, event):
    if event.modifiers() == Qt.ControlModifier:
    # Check if mouse wheel up or down
    if event.angleDelta().y() > 0:
    zoom_factor = self.zoom_in_factor
    self.zoom += self.zoom_step
    else:
    zoom_factor = 1 / self.zoom_in_factor
    self.zoom -= self.zoom_step

    # Clamping
    clamped = False
    if self.zoom < self.zoom_range[0]:
    self.zoom = self.zoom_range[0]
    clamped = True
    if self.zoom > self.zoom_range[1]:
    self.zoom = self.zoom_range[1]
    clamped = True

    if not clamped or self.zoom_clamp is False:
    self.scale(zoom_factor, zoom_factor)

    self.scene.update()

    else:
    return super().wheelEvent(event)

    app = QApplication([sys.argv])

    view = View()
    view.show()

    app.exec()


    This code works as I want to on my Windows laptop (Asus ROG Flow X13). When I do a swipe gesture it calls the super method and handles it accordingly and (I don't know why) on a pinch gesture PyQt thinks that I am holding control and therefore executes the zooming part of the code. However on a MacBook (as you would expect) the super method is called always (except when I hold down cmd). Therefore the zooming does not work with a pinch gesture there but the panning works.

    I've tested usingQGestures to implement the zooming with this code:

    import sys

    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *

    class View(QGraphicsView):
    def __init__(self, parent=None):
    super().__init__(parent)

    self.grabGesture(Qt.PinchGesture)
    self.grabGesture(Qt.SwipeGesture)

    self.scene = QGraphicsScene()
    self.scene.setSceneRect(-5000, -5000, 10000, 10000)
    self.scene.addRect(0, 0, 100, 100, QPen(Qt.NoPen), QBrush(Qt.green))

    self.setScene(self.scene)

    def event(self, event):
    if event.type() == QEvent.Gesture:
    return self.gestureEvent(QGestureEvent(event))
    return super().event(event)

    def gestureEvent(self, event):
    print("Gesture event")

    if event.gesture(Qt.PinchGesture):
    print("Pinch gesture")
    self.pinchTriggered(QPinchGesture(event.gesture(Qt.PinchGesture)))
    if event.gesture(Qt.SwipeGesture):
    print("Swipe gesture")
    self.swipeTriggered(QSwipeGesture(event.gesture(Qt.SwipeGesture)))

    print()
    return True

    def pinchTriggered(self, gesture):
    changeFlags = gesture.changeFlags()

    if changeFlags & QPinchGesture.ScaleFactorChanged:
    print("Scale factor changed", gesture.scaleFactor(), gesture.totalScaleFactor(), gesture.lastScaleFactor())

    def swipeTriggered(self, gesture):
    pass

    app = QApplication([sys.argv])

    view = View()
    view.show()

    app.exec()


    While testing with this code the following things happend on the different platforms: On Windows no gestures are registered. On Mac only the the pinch gesture was registered. Therefore I tried realising the zooming on Mac with a pinch gesture trying a similar approach to the official PyQt docs. This did not seem to work because the scaleFactor, totalScaleFactor and totalScaleFactor of the QPinchGesture do not change when doing the pinch gesture. They always stays at 1.0.

    Is it possible to fix this error or is there any other approach than QGestures to solve this problem?

    Continue reading...

Compartilhe esta Página