QGraphicsView如何使图片以鼠标为中心进行放缩
顺带说一句,下面的代码放在了一个继承了QMainWindow的自定义class里面,这个类包含着一个QGraphicsView部件,所有以下的代码都会以为处在类中而出现对应的首行缩进。
QGraphicsView的自带语句实现
因为QGraphicsView是从Qt整个改过来的,自然包含了所有的部件,其中就有所用到的三句话:
self.ui.graphicsView.setDragMode(QGraphicsView.ScrollHandDrag)
self.ui.graphicsView.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
self.ui.graphicsView.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
可以很清楚地发现,第一句是自带的拖动效果的实现,第二句是说将变换的锚点设置到鼠标的下面,第三句话说的是将图元重设大小时的锚点设置到鼠标下面,这里就将放大缩小的点设置到了鼠标的下面。这样一来就可以通过指定点进行放大缩小。
QGraphicsView的事件重写实现
那么问题来了,我如果有一个自定义的函数需要写的话,怎么跟这个已有的方法结合起来呢?类的继承是可以,但是这家伙看着也不像一个类啊,倒像是一个方法,那我们除了将_文档_找出来慢慢研读,就是自己实现所有的操作了,文档可以去官方查找,里面用的是当前鼠标坐标与整个视图坐标的比值,再通过比值确定滚动条的位置进行操作,下方的滚动条设置偏左,右边的滚动条设置偏上 ,就能使得图片进行左上为中心的变换,至于具体位置根据图元与视图的比值进行计算就可以。
但是我有一个__更简单的逻辑__,就是将图片的重绘点设置在一个变化后的点,这个点也是通过计算算出来的,但是不同的是,这个点的坐标比较容易计算,并且没有涉及到任何其他部件,只是单纯更新一个点然后进行重绘。这个点的计算方法我会详细介绍给大家。
重写过程中涉及到的事件
既然自己重写了,那么鼠标的所有事件都要自己来一遍
之前讲过图片的放大缩小和移动,但是那个放缩是改变了滑动条,不能指哪变哪,所以这次的鼠标滑动事件和鼠标移动事件都要稍微改动一下。
自定义滚轮事件的实现逻辑
第一步:提取图片的左上和右下两个点来确定计算所需要的参数:图元第一次绘制的setPos()、图片转来的图片的尺寸;第二步:获取鼠标当前坐标值以进行计算;第三步:计算出差值偏移量delta;第四步:进行图元的重绘。
对于滚轮事件计算的说明
滚轮事件的第三步有一个计算出delta差值,这里截出来代码给大家看看:
# -*- coding: utf-8 -*-
"""
@author:xiaoyangchicao2020
@time:2022-99-99
"""
self.item.setScale(self.ratio)
a1=self.posss - self.item.pos()
a2=self.ratio/(self.ratio-self.step)-1
self.delta = a1 * a2
self.posnow=self.item.pos()-self.delta
self.item.setPos(self.posnow)
self.ratio是一个int,说的是图片初始的大小比例,一般设为1。self.posss就是鼠标现在相对于view的坐标了,就是==mapToscne(event.pos())==这个方法返回的值,是鼠标当前坐标,是一个QPoinF,然后用这个坐标减去图元一开始所在的坐标,也就是setPos()的那个坐标点。self.step就是图片缩放的步长,太大了图片突变,我设置的是0.3,按照这个数学运算最终会得出一个点,这个点就是需要变换的坐标差值,用图元之前的坐标减去差值,就是图元现在应该重新设置的地方,就是那个self.posnow,图片在这个点重绘之后就能得到以鼠标为中心的放大缩小的效果。
完整代码如下):文章来源:https://www.toymoban.com/news/detail-647411.html
# -*- coding: utf-8 -*-
"""
@author:xiaoyangchicao2020
@time:2022-99-99
"""
self.ratio = 1#缩放系数
self.step = 0.3 #缩放步长
self.posnow = QPointF(0, 0) # 图片绘制位置
def wheel_Event_tinghua(self,event):
angle = event.angleDelta() / 8
angley = angle.y()
self.posss=self.ui.graphicsView.mapToScene(event.pos())
if angley > 0:
self.ratio+=self.step
w = math.ceil(self.pix.width()*(self.ratio-self.step))
h = math.ceil(self.pix.height()*(self.ratio-self.step))
x1=self.item.pos().x()
x2=self.item.pos().x()+w
y1=self.item.pos().y()
y2=self.item.pos().y()+h
if self.posss.x() > x1 and self.posss.x() < x2 * self.ratio \
and self.posss.y() > y1 and self.posss.y() < y2 * self.ratio:
self.inimg = True
self.item.setScale(self.ratio)
value1=self.posss - self.item.pos()
value2=self.ratio/(self.ratio-self.step)-1
self.delta = value1 * value2
self.posnow=self.item.pos()-self.delta
self.item.setPos(self.posnow)
else:
pass
elif angley < 0:
self.ratio -= self.step
w = math.ceil(self.pix.width() * (self.ratio + self.step))
h = math.ceil(self.pix.height() * (self.ratio + self.step))
x1 = self.item.pos().x()
x2 = self.item.pos().x() + w
y1 = self.item.pos().y()
y2 = self.item.pos().y() + h
if self.posss.x() > x1 and self.posss.x() < x2 * self.ratio \
and self.posss.y() > y1 and self.posss.y() < y2 * self.ratio:
self.inimg = True
self.item.setScale(self.ratio)
value1=self.posss - self.item.pos()
value2=self.ratio/(self.ratio+self.step)-1
self.delta = value1 * value2
self.posnow = self.item.pos()-self.delta
self.item.setPos(self.posnow)
else:
pass
看起来很长其实只是因为判断语句和前期获取计算需要的数据进行的工作比较多,其实逻辑还是很清晰的。文章来源地址https://www.toymoban.com/news/detail-647411.html
到了这里,关于QGraphicsView如何使图片以鼠标为中心进行放缩的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!