前段时间用了QGraphicsView做了一些工作,然而如何实现QGraphicsView的放大缩小的效果也很简单,照鼠标某一点进行缩放,仅靠以下代码对view进行缩放会导致view上的item在放大缩小的过程中跑偏了。
void CustomView::wheelEvent(QWheelEvent *event){// 当前放缩倍数;qreal scaleFactor = this->matrix().m11();int wheelDeltaValue = event->delta();// 向上滚动,放大;if (wheelDeltaValue >0){this->scale(1.2, 1.2);}// 向下滚动,缩小;else{this->scale(1.0 / 1.2, 1.0 / 1.2);}}我们看一下仅靠以上代码实现的放大缩小的效果。
(相关资料图)
从下图中我们看到把图中小矩形放到屏幕中央进行放大缩小时,效果还是可以的,但是当我们吧小矩形拖到屏幕靠左位置时(或者靠右,只要不是中央位置),我们发现放大所需时小矩形位置偏移较为严重,为了就解决这个问题,闭关修炼了三天,终于解决了。期间各种百度,看助手文档,后来有位小伙伴推荐了一篇文章用MFC实现了图片按照鼠标点进行放大缩小效果,虽然达到了类似的效果,但是和QGraphicsView的原理不一样。那篇文章中通过放大后重新计算图片的位置,然后在对应位置进行重绘。
最后的最后,在QGraphicsView的源码中找到了方法的思路。
我们再看一下百度地图放大缩小的效果(因为受到了图片大小的限制,就截了一小块)。
大家可以看到鼠标分别放到两个绿色矩形区域进行放大缩小的效果,可以看到都是按照鼠标点进行缩放的。
好了,上面说明了问题,下面就开始针对这个问题进行解决。话不多说,直接上代码。
void CustomView::wheelEvent(QWheelEvent *event){// 获取当前鼠标相对于view的位置;QPointF cursorPoint = event->pos();// 获取当前鼠标相对于scene的位置;QPointF scenePos = this->mapToScene(QPoint(cursorPoint.x(), cursorPoint.y()));// 获取view的宽高;qreal viewWidth = this->viewport()->width();qreal viewHeight = this->viewport()->height();// 获取当前鼠标位置相当于view大小的横纵比例;qreal hScale = cursorPoint.x() / viewWidth;qreal vScale = cursorPoint.y() / viewHeight;// 当前放缩倍数;qreal scaleFactor = this->matrix().m11();int wheelDeltaValue = event->delta();// 向上滚动,放大;if (wheelDeltaValue >0){this->scale(1.2, 1.2);}// 向下滚动,缩小;else{this->scale(1.0 / 1.2, 1.0 / 1.2);}// 将scene坐标转换为放大缩小后的坐标;QPointF viewPoint = this->matrix().map(scenePos);// 通过滚动条控制view放大缩小后的展示scene的位置;horizontalScrollBar()->setValue(int(viewPoint.x() - viewWidth * hScale));verticalScrollBar()->setValue(int(viewPoint.y() - viewHeight * vScale));}通过上面的代码即可实现QGraphicsView按照鼠标点进行放大缩小的效果。
我们看一下效果,图一中我分别将将小矩形拖到屏幕的上、下、左、右四个方位,我们发现都是按照鼠标点进行了放缩(gif图录制软件在拖到小矩形时生成的图片有点阴影,大家可以忽略)。
图二中,分别将鼠标放置在屏幕的四角,我们可以看到很明确的效果。
图一
图二
附上一张效果图(可能需要放大网页看,相对清楚一点)
下面是QGraphicsView::centerOn(const QPointF &pos)方法的源码。以上代码也是参考了这个方法后得到的结果。这个方法也就是通过滑动滚动条的方法将所给的点(该点是相对于scene的)放置在view 的中央位置。而我们想要实现按照鼠标点进行放大缩小效果,只需要计算当前鼠标位置相对于view大小的比例,centerOn方法中是 1/2 ,我们只要替换为相对应的比例即可。
/*!Scrolls the contents of the viewport to ensure that the scenecoordinate \a pos, is centered in the view.Because \a pos is a floating point coordinate, and the scroll bars operateon integer coordinates, the centering is only an approximation.
ote If the item is close to or outside the border, it will be visiblein the view, but not centered.\sa ensureVisible()*/void QGraphicsView::centerOn(const QPointF &pos){Q_D(QGraphicsView);qreal width = viewport()->width();qreal height = viewport()->height();QPointF viewPoint = d->matrix.map(pos);QPointF oldCenterPoint = pos;if (!d->leftIndent) {if (isRightToLeft()) {qint64 horizontal = 0;horizontal += horizontalScrollBar()->minimum();horizontal += horizontalScrollBar()->maximum();horizontal -= int(viewPoint.x() - width / 2.0);horizontalScrollBar()->setValue(horizontal);} else {horizontalScrollBar()->setValue(int(viewPoint.x() - width / 2.0));}}if (!d->topIndent)verticalScrollBar()->setValue(int(viewPoint.y() - height / 2.0));d->lastCenterPoint = oldCenterPoint;}【领 QT开发教程 学习资料, 点击下方链接莬费领取↓↓ ,先码住不迷路~】
点击这里:
一、简述前段时间用了QGraphicsView做了一些工作,然而如何实现QGraphicsView的放大缩小的效果也很简单,照
你需要的东西大搅拌碗小碗深煎锅钳叉大汤匙纸巾2 3杯面粉1汤匙。橙花水1 4杯糖2汤匙。植物油1个鸡蛋2茶匙。
抄写作文网小编为大家提供小学需要背哪些古诗小学生必背古诗有什么来供大家参考,欢迎阅读。小学生必背古诗
来为大家解答以下的问题,义和要旨的区别,要义这个很多人还不知道,现在让我们一起来看看吧!1、意思:指重
X 关闭
“没坐头”到“天天像过年”:“花儿”唱响西北民众生活变化轨迹
抵返人员发现2例初筛阳性 牡丹江开展区域核酸检测
中企承建尼日利亚最大水电站:年内还将实现3台机组发电目标
安徽淮南新增确诊病例1例、新增无症状感染者50人
徐州疫情阳性感染者升至17例 八里小学隔离177名次密接师生
X 关闭
QGraphicsView实现鼠标放缩 天天快看
【快播报】如何制作 Bitso Pinoy_女生送给男性朋友的生日礼物
小学需要背哪些古诗 小学生必背古诗 有什么
天天动态:要义和要旨的区别(要义)
绿洲这个软件是干嘛的_绿洲app是干什么的_实时