因此,让我说我有一个简单的QGraphicsView和QGraphicsScene,我想动画的视图顺利滚动/缩放到场景中的任意QRecF。我知道您可以调用view.fitInView()或view.centerOn()在rect上“帧”,但是这些都不能提供太多的动画。我可以反复调用view.centerOn()来很好地动画滚动,但这不能处理缩放。我认为我需要修改视图的视图,但我不太确定如何做到这一点(调用view.setSceneRect()似乎很有希望,但这只是设置视图可以管理的区域,而不是它目前正在“查看”的区域)。
基于一些C++的答案,我想出了如何重写fitInView方法,但是我仍然停留在不调用centerOn的情况下将视图转换为look at的部分。到目前为止,我的情况如下:
view = QtWidgets.QGraphicsView()
scene = QtWidgets.QGraphicsScene()
targetRect = QtCore.QRectF(500, 500, 500, 500)
viewRect = view.viewport().rect()
sceneRect = view.transform().mapRect(targetRect)
xratio = viewRect.width() / sceneRect.width()
yratio = viewRect.height() / sceneRect.height()
# keep aspect
xratio = yratio = min(xratio, yratio)
# so... now what to do with the ratio? I need to scale the view rect somehow.
# animation
start = view.mapToScene(viewRect).boundingRect()
end = sceneRect # I guess?
animator = QtCore.QVariantAnimation()
animator.setStartValue(start)
animator.setEndValue(end)
animator.valueChanged.connect(view.????) # what am I setting here?
animator.start()发布于 2021-12-14 22:30:13
我走了很多弯弯曲曲的路,结果得到了一个非常简单的答案,我想我会把它发出去,以防有人发现它同时对滚动和缩放都有帮助:
view = QtWidgets.QGraphicsView()
scene = QtWidgets.QGraphicsScene()
targetRect = QtCore.QRectF(500, 500, 500, 500)
animator = QtCore.QVariantAnimation()
animator.setStartValue(view.mapToScene(view.viewport().rect()).boundingRect())
animator.setEndValue(targetRect)
animator.valueChanged.connect(lambda x: view.fitInView(x, QtCore.Qt.KeepAspectRatio))
animator.start()发布于 2021-12-14 23:43:09
一个简单的基本解决方案是映射目标矩形并使用该值作为动画的结束值。
请注意,这个解决方案实际上并不是最优的,原因有两个:
它完全依赖于transformation;
scale()或setTransform(),并在当前映射的setTransform()矩形上调用centerOn() --场景重排可能比视图显示的要小,放大可能会有点尴尬;class SmoothZoomGraphicsView(QtWidgets.QGraphicsView):
def __init__(self):
super().__init__()
scene = QtWidgets.QGraphicsScene()
self.setScene(scene)
self.pixmap = scene.addPixmap(QtGui.QPixmap('image.png'))
self.animation = QtCore.QVariantAnimation()
self.animation.valueChanged.connect(self.smoothScale)
self.setTransformationAnchor(self.AnchorUnderMouse)
def wheelEvent(self, event):
viewRect = self.mapToScene(self.viewport().rect()).boundingRect()
# assuming we are using a basic x2 or /2 ratio, we need to remove
# a quarter of the width/height and translate to half the position
# betweeen the current rectangle and cursor position, or add half
# the size and translate to a negative relative position
if event.angleDelta().y() > 0:
xRatio = viewRect.width() / 4
yRatio = viewRect.height() / 4
translate = .5
else:
xRatio = -viewRect.width() / 2
yRatio = -viewRect.height() / 2
translate = -1
finalRect = viewRect.adjusted(xRatio, yRatio, -xRatio, -yRatio)
cursor = self.viewport().mapFromGlobal(QtGui.QCursor.pos())
if cursor in self.viewport().rect():
line = QtCore.QLineF(viewRect.center(), self.mapToScene(cursor))
finalRect.moveCenter(line.pointAt(translate))
self.animation.setStartValue(viewRect)
self.animation.setEndValue(finalRect)
self.animation.start()
def smoothScale(self, rect):
self.fitInView(rect, QtCore.Qt.KeepAspectRatio)https://stackoverflow.com/questions/70355703
复制相似问题