0

I am trying to implement zooming in/out feature on Qt and I've tried almost all methods on this post, but none of them works.

It can zoom in/out with right ratio, but y position jumps randomly after wheeling (x position seems correct)

Reproduce on Qt creator:

  1. Create Qt Widgets Application
  2. On "design" page, drag a Graphics View from "Display Widgets" (Default objectName is "graphicsView")
  3. Declare 1 variable, 3 functions and 1 private slots on MainWindow.h
public:
    QGraphicsView* m_pDrawingArea;
    void setupView();
    void setupDefaultDrawing();
    void eventDrawingArea_Wheel(QWheelEvent* event);
private slots:
    bool eventFilter(QObject* object, QEvent* event) override;
  1. set up variable and function calls in contructor
ui->setupUi(this);
    m_pDrawingArea = findChild<QGraphicsView*>("graphicsView");
    setupView();
    setupDefaultDrawing();
  1. fill setupView() and setupDefaultDrawing()
void MainWindow::setupView(){
    QGraphicsScene* pScene = new QGraphicsScene(this);
    m_pDrawingArea->setScene(pScene);
    //reverse y axis
    m_pDrawingArea->scale(1, -1);
    //mouse event
    m_pDrawingArea->setMouseTracking(true);
    m_pDrawingArea->viewport()->installEventFilter(this);
    //set viewportupdatemode to fullview
    m_pDrawingArea->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
}
void MainWindow::setupDefaultDrawing(){
    //use two axis to extend scence
    int width = m_pDrawingArea->width()*100;
    int height = m_pDrawingArea->height()*100;
    QGraphicsLineItem* pXAxis = new QGraphicsLineItem(-width / 2, 0, width / 2, 0);
    QGraphicsLineItem* pYAxis = new QGraphicsLineItem(0, -height / 2, 0, height / 2);
    m_pDrawingArea->scene()->addItem(pXAxis);
    m_pDrawingArea->scene()->addItem(pYAxis);
    //a point for test
    QGraphicsEllipseItem* pPoint = new QGraphicsEllipseItem(100, 100, 1, 1);
    pPoint->setPen(QPen(Qt::black, 1, Qt::SolidLine));
    pPoint->setBrush(QBrush(Qt::black));
    m_pDrawingArea->scene()->addItem(pPoint);
}
  1. create mouse wheel event
bool MainWindow::eventFilter(QObject* object, QEvent* event){
    if (object == m_pDrawingArea->viewport() && event->type() == QEvent::Wheel){
        eventDrawingArea_Wheel(static_cast<QWheelEvent*>(event));
    }
    return QMainWindow::eventFilter(object, event);
}
void MainWindow::eventDrawingArea_Wheel(QWheelEvent* wheelEvent){
    QPointF oldPos = m_pDrawingArea->mapToScene(wheelEvent->pos());
    if (wheelEvent->modifiers() & Qt::ControlModifier) {
        // zoom
        QGraphicsView::ViewportAnchor anchor = m_pDrawingArea->transformationAnchor();
        m_pDrawingArea->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
        int angle = wheelEvent->angleDelta().y();
        qreal scaleFactor = (angle > 0) ? 1.25 : 1 / 1.25;
        m_pDrawingArea->scale(scaleFactor, scaleFactor);
        QPointF newPos = m_pDrawingArea->mapToScene(wheelEvent->pos());
        m_pDrawingArea->translate(newPos.x() - oldPos.x(), newPos.y() - oldPos.y());
        m_pDrawingArea->setTransformationAnchor(anchor);
    } else {
//            QGraphicsView::wheelEvent(wheelEvent);
    }
}
BoKuan Liu
  • 21
  • 1
  • 6

1 Answers1

0

Solved by blocking scrollbar signals and setting v/h scroll bar policy to "ScrollBaryAlwaysOff"

m_pDrawingArea->verticalScrollBar()->blockSignals(true);
m_pDrawingArea->horizontalScrollBar()->blockSignals(true);
BoKuan Liu
  • 21
  • 1
  • 6