1

I am looking to find how to zoom in a QGraphicsView but on the cursor position. Currently I am able to zoom but the position it is zooming onto is not consistent.

    def wheelEvent(self, event):
        '''Wheel event to zoom
        '''
        # Run default event
        QtWidgets.QGraphicsView.wheelEvent(self, event)

        # Define zoom factor
        factor = 1.1
        if event.delta() < 0:
            factor = 0.9

        self.scale(factor, factor)

I have seen the use of self.mapToScene() but have been unsuccessful

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Adam Baker
  • 44
  • 8

1 Answers1

5

A possible solution is to focus on the point where the mouse is, scale and recalculate the point where the new center should be:

def wheelEvent(self, event):
    factor = 1.1
    if event.delta() < 0:
        factor = 0.9
    view_pos = event.pos()
    scene_pos = self.mapToScene(view_pos)
    self.centerOn(scene_pos)
    self.scale(factor, factor)
    delta = self.mapToScene(view_pos) - self.mapToScene(self.viewport().rect().center())
    self.centerOn(scene_pos - delta)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • The problem with mapToScene(QPoint) is that it's not that precise due to the integer nature of QPoint. I think that (as [documentation suggests](https://doc.qt.io/qt-5/qgraphicsview.html#mapToScene) too) it's better to map to the QRect covered by the mouse position, and then use 'centerOn` against `scene_pos.boundingRect().center()`. – musicamante Nov 21 '19 at 00:34
  • @musicamante I have used it several times and I have not observed that error. Have you tested it? I have not been able to test it so far. – eyllanesc Nov 21 '19 at 00:37
  • I've had similar problems in the past; while they're usually trivial, it can sometimes be annoying when zooming in. I've just tested with a basic grid and I can confirm that there's always a -1, -1 pixel offset (based on the pixel size of the transform *before* scaling) that is applied recursively as the scale increments. [This image](https://i.stack.imgur.com/7p7cN.png) shows the zoomed images of origin point on the left, and the results of two steps of mouse wheel, with the mapToScene(QPoint) in the middle and mapToScene(QRect) on the right. – musicamante Nov 21 '19 at 01:16
  • This obviously assumes that the cursor hotspot is correctly set in its definition. I'm pretty sure that mine's correctly set in the area occupied by the topleft corner pixel of my cursor; I might be wrong, but I believe that in that case the offset would be even bigger (in one direction or the other). Also, if the cursor position is left untouched, there will always be some amount of offset in any case, but I believe that the QRect map method is more precise. A possible workaround I think that the new position could be set by taking into account the QTransform, but that's another... point ;-) – musicamante Nov 21 '19 at 01:22