Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Moving a graphics scene in a graphics view on middle click



  • I am trying to move the scene of a QGraphicsView when clicking the middle mouse button.
    So I subclassed QGraphicsView and have overwritten mouseMouseEvent. I have a vector for the movement like this:

    const auto movement = mapToScene(event->pos() - lastCursorPosition);
    

    Now, my issue is that translate() uses the transformation anchor. Here is what happens with each anchor:

    • NoAnchor: Movement is correct, but always starts in the top left. This is unusable for me, since I want to translate the current view.
    • AnchorUnderMouse: Movement is way too fast. When I move the mouse, I move the anchor, which makes the movement way bigger than I wanted
    • AnchorViewCenter: Nothing moves, because the center is always centered.

    Now, I tried the following things:

    • use NoAnchor and translate to the current mouse position. No effect since the next translate() moves back to top left
    • use AnchorUnderMouse and translate with 0 / 1 / a fraction of the vector. Movement still way too fast.
    • set DragMode to ScrollHandDrag and send a mouseMoveEvent(newEvent) to the parent, overriding buttons with LeftButton whenever a MiddleButton is received. No resulte since parent seems to be prioritized.
    • change the position of horizontal and vertical scrollbars instead of using translate, as Qt does with ScrollHandDrag. Not possible, since I cant access the necessary functions.

    So, my question is: How do I move the scene of a view when the user drags the mouse with middle button pressed?

    If needed, here are the interesting functions:

    void GraphicsView::mousePressEvent(QMouseEvent *event) {
        if (event->button() == Qt::MiddleButton) {
            setCursor(Qt::DragMoveCursor);
            lastCursorPosition = event->pos();
            event->accept();
        }
        QGraphicsView::mousePressEvent(event);
    }
    
    void GraphicsView::mouseMoveEvent(QMouseEvent *event) {
        if (event->buttons() == Qt::MiddleButton) {
            // FIXME scene is always moved from the top left corner
            setTransformationAnchor(AnchorUnderMouse);
            const auto movement = mapToScene(event->pos() - lastCursorPosition);
            translate(movement.x(), movement.y());
            event->accept();
        } else
            QGraphicsView::mouseMoveEvent(event);
    }
    
    void GraphicsView::mouseReleaseEvent(QMouseEvent *event) {
        unsetCursor();
        QGraphicsView::mouseReleaseEvent(event);
    }
    

Log in to reply