Qt动画使用QPropertyAnimation同时更改比例和位置

2024-09-29 21:23:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在尝试在QAnimation框架的帮助下用Qt构建一个幻灯片查看器。我在改变照片大小的同时移动它有困难,因为在幻灯片中改变照片的大小,而它正在移动似乎会影响它的轨迹。在

具体地说,我正在尝试设置一组照片的动画,使它们在窗口的水平中心线上从右到左连续移动,同时改变大小。基本上,这是一种“鱼眼”效应,当照片向窗口中心移动时,照片会变大,然后随着移动而减小到原来的大小。在

在任何给定的时间,窗口将只显示3张照片(加上1张从左侧窗口退出的照片)。假设这3张照片,从左到右排列,标记为P1、P2、P3。考虑一张照片,最右边的照片P3。当P3从窗口右侧向中心移动时,其大小应逐渐增大,并在窗口中心达到最大大小。当它继续向左移动并最终退出窗口时,它的大小应该会减小到原来的值。在

如果我只是移动照片而不调整它们的大小,我当前的实现是有效的。当同时移动和缩放图像时,照片不再在窗口中心水平移动。照片的大小似乎缩放正确。在

我当前的实现依赖于QPropertyAnimation类来执行动画。我用Python和Qt的pyStand绑定编写程序,但是C++或PyQT代码中的解决方案很好。我将把它们翻译成Python和PySide。在

相关代码如下:

def animate(self, items):
'''@params: items The photos to animate'''
    logging.debug('Creating %d animation objects', len(items))
    self.animationGroup.clear()
    for i, item in enumerate(items):
        self.animatePosition(item, i, len(items))
        self.animateScale(item, i)
    QTimer.singleShot(START_DELAY, self.animationGroup.start)    

def animatePosition(self, item, index, numItems):
    isLastItem = (index == numItems - 1)
    isFirstItem = (index == 0)

    posAnimation = QPropertyAnimation(item, 'position')
    posAnimation.setDuration(SLIDE_INTERVAL)
    posAnimation.setStartValue(item.pos())
# I've tried changing dh depending on the scale of the current image with limited success.
dh = 0 
    if isLastItem:
        posAnimation.setEndValue(item.pos() - QPointF(slideshow.RIGHT_MARGIN + slideshow.STANDARD_SLIDE_WIDTH, dh))
    elif isFirstItem:
        posAnimation.setEndValue(item.pos() - QPointF(slideshow.LEFT_MARGIN + slideshow.STANDARD_SLIDE_WIDTH, dh))
    else:
        posAnimation.setEndValue(item.pos() - QPointF(slideshow.IMAGE_GAP + slideshow.STANDARD_SLIDE_WIDTH, dh))
    posAnimation.setEasingCurve(QEasingCurve.OutExpo)
    self.animationGroup.addAnimation(posAnimation)

def animateScale(self, item, index):
    if self.animatedView is not None:
        scaleAnimation = QPropertyAnimation(item, 'slideScale')
        scaleAnimation.setDuration(SLIDE_INTERVAL)
        scaleAnimation.setStartValue(item.scale())
        endScale = self.getSlideScale(index - 1)
        scaleAnimation.setEndValue(endScale)
        scaleAnimation.setEasingCurve(QEasingCurve.OutExpo)
        self.animationGroup.addAnimation(scaleAnimation)

我知道,通常情况下,在应用缩放变换之前,必须将照片移回原点,然后再移回轨迹上的下一个位置。我怀疑用于缩放照片的QPropertyAnimation正在应用于翻译的照片,因此影响了它的轨迹,但我可能错了,因为我在过去的1-2周才开始使用Qt。在

有人知道我如何使一个QPropertyAnimation知道另一个动画正在发生吗?或者有人能提出一种不同的方法(不一定涉及QPropertyAnimation)来解决上述问题吗?在

提前感谢您的回复。在


Tags: posselfindexitemsitem中心照片dh
1条回答
网友
1楼 · 发布于 2024-09-29 21:23:35

我假设您使用的是QGraphicsView框架(如果您发布了一个最小的、正在运行的示例程序,那么理解和调试您的问题会更加容易)。在

我建议使用QGraphicsWidgets并直接为它们的"geometry" property设置动画(编辑:我错了,这不能工作)。在

您需要同时更改大小和位置,而不使用两个QPropertyAnimations。最简单的解决方案可能是将一个qvarianimation(甚至qvarianimation)子类化并适当地实现updateCurrentValue()。我想我应该插值一个QRectF,从中你可以提取位置和大小/比例,否则你当然可以只插值一个浮点(这意味着您将有更多的插值代码自己做,但它可以绕过必须从大小计算比例)。考虑将所需的比例编组成QRectF的大小(例如,将QSizeF(scale, scale)传递给构造函数)。这有点老套,因为QRectF不再是/不是/所需的项目几何体,但在其他方面很简单,工作非常好(也可以使用缓和曲线)。下面是一个有用的片段:

class GeometryAnimation(QtCore.QVariantAnimation):
    def __init__(self, item, parent = None):
        QtCore.QVariantAnimation.__init__(self, parent)
        self._item = item

    def updateCurrentValue(self, value):
        self._item.setPos(value.topLeft())
        self._item.setScale(value.width())

为什么您当前的代码不工作很难说,并且取决于“slideScale”属性的实现;如果转换相互作用(我认为这是不希望的行为),那就是原因。在

相关问题 更多 >

    热门问题