当前位置:   article > 正文

QGraphicsView 如何实现百度地图按照鼠标点进行放大缩小效果_qt中svg图随鼠标进行缩放

qt中svg图随鼠标进行缩放

一、简述

前段时间用了QGraphicsView做了一些工作,然而如何实现QGraphicsView的放大缩小的效果也很简单,照鼠标某一点进行缩放,仅靠以下代码对view进行缩放会导致view上的item在放大缩小的过程中跑偏了。

  1. void CustomView::wheelEvent(QWheelEvent *event)
  2. {
  3. // 当前放缩倍数;
  4. qreal scaleFactor = this->matrix().m11();
  5. int wheelDeltaValue = event->delta();
  6. // 向上滚动,放大;
  7. if (wheelDeltaValue > 0)
  8. {
  9. this->scale(1.2, 1.2);
  10. }
  11. // 向下滚动,缩小;
  12. else
  13. {
  14. this->scale(1.0 / 1.2, 1.0 / 1.2);
  15. }
  16. }

我们看一下仅靠以上代码实现的放大缩小的效果。

从下图中我们看到把图中小矩形放到屏幕中央进行放大缩小时,效果还是可以的,但是当我们吧小矩形拖到屏幕靠左位置时(或者靠右,只要不是中央位置),我们发现放大所需时小矩形位置偏移较为严重,为了就解决这个问题,闭关修炼了三天,终于解决了。期间各种百度,看助手文档,后来有位小伙伴推荐了一篇文章用MFC实现了图片按照鼠标点进行放大缩小效果,虽然达到了类似的效果,但是和QGraphicsView的原理不一样。那篇文章中通过放大后重新计算图片的位置,然后在对应位置进行重绘。

最后的最后,在QGraphicsView的源码中找到了方法的思路。

 

我们再看一下百度地图放大缩小的效果(因为受到了图片大小的限制,就截了一小块)。

大家可以看到鼠标分别放到两个绿色矩形区域进行放大缩小的效果,可以看到都是按照鼠标点进行缩放的。

 

二、代码之路

好了,上面说明了问题,下面就开始针对这个问题进行解决。话不多说,直接上代码。

  1. void CustomView::wheelEvent(QWheelEvent *event)
  2. {
  3. // 获取当前鼠标相对于view的位置;
  4. QPointF cursorPoint = event->pos();
  5. // 获取当前鼠标相对于scene的位置;
  6. QPointF scenePos = this->mapToScene(QPoint(cursorPoint.x(), cursorPoint.y()));
  7. // 获取view的宽高;
  8. qreal viewWidth = this->viewport()->width();
  9. qreal viewHeight = this->viewport()->height();
  10. // 获取当前鼠标位置相当于view大小的横纵比例;
  11. qreal hScale = cursorPoint.x() / viewWidth;
  12. qreal vScale = cursorPoint.y() / viewHeight;
  13. // 当前放缩倍数;
  14. qreal scaleFactor = this->matrix().m11();
  15. int wheelDeltaValue = event->delta();
  16. // 向上滚动,放大;
  17. if (wheelDeltaValue > 0)
  18. {
  19. this->scale(1.2, 1.2);
  20. }
  21. // 向下滚动,缩小;
  22. else
  23. {
  24. this->scale(1.0 / 1.2, 1.0 / 1.2);
  25. }
  26. // 将scene坐标转换为放大缩小后的坐标;
  27. QPointF viewPoint = this->matrix().map(scenePos);
  28. // 通过滚动条控制view放大缩小后的展示scene的位置;
  29. horizontalScrollBar()->setValue(int(viewPoint.x() - viewWidth * hScale));
  30. verticalScrollBar()->setValue(int(viewPoint.y() - viewHeight * vScale));
  31. }

通过上面的代码即可实现QGraphicsView按照鼠标点进行放大缩小的效果。

我们看一下效果,图一中我分别将将小矩形拖到屏幕的上、下、左、右四个方位,我们发现都是按照鼠标点进行了放缩(gif图录制软件在拖到小矩形时生成的图片有点阴影,大家可以忽略)。

图二中,分别将鼠标放置在屏幕的四角,我们可以看到很明确的效果。

图一

 

图二

 

附上一张效果图(可能需要放大网页看,相对清楚一点)

 

 

下面是QGraphicsView::centerOn(const QPointF &pos)方法的源码。以上代码也是参考了这个方法后得到的结果。这个方法也就是通过滑动滚动条的方法将所给的点(该点是相对于scene的)放置在view 的中央位置。而我们想要实现按照鼠标点进行放大缩小效果,只需要计算当前鼠标位置相对于view大小的比例,centerOn方法中是 1/2 ,我们只要替换为相对应的比例即可。

  1. /*!
  2. Scrolls the contents of the viewport to ensure that the scene
  3. coordinate \a pos, is centered in the view.
  4. Because \a pos is a floating point coordinate, and the scroll bars operate
  5. on integer coordinates, the centering is only an approximation.
  6. \note If the item is close to or outside the border, it will be visible
  7. in the view, but not centered.
  8. \sa ensureVisible()
  9. */
  10. void QGraphicsView::centerOn(const QPointF &pos)
  11. {
  12. Q_D(QGraphicsView);
  13. qreal width = viewport()->width();
  14. qreal height = viewport()->height();
  15. QPointF viewPoint = d->matrix.map(pos);
  16. QPointF oldCenterPoint = pos;
  17. if (!d->leftIndent) {
  18. if (isRightToLeft()) {
  19. qint64 horizontal = 0;
  20. horizontal += horizontalScrollBar()->minimum();
  21. horizontal += horizontalScrollBar()->maximum();
  22. horizontal -= int(viewPoint.x() - width / 2.0);
  23. horizontalScrollBar()->setValue(horizontal);
  24. } else {
  25. horizontalScrollBar()->setValue(int(viewPoint.x() - width / 2.0));
  26. }
  27. }
  28. if (!d->topIndent)
  29. verticalScrollBar()->setValue(int(viewPoint.y() - height / 2.0));
  30. d->lastCenterPoint = oldCenterPoint;
  31. }

 进群领取qt开发学习资料以及技术交流  在下方↓↓↓↓↓↓↓↓

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/91715
推荐阅读
相关标签
  

闽ICP备14008679号