我目前正尝试在QAnimation框架的帮助下使用Qt构建幻灯片查看器。我无法改变照片的大小,同时移动照片,因为在幻灯片放映时改变照片的大小似乎会影响其轨迹。
具体来说,我正在尝试为一组照片制作动画,使它们在窗口的水平中心线上从右向左连续移动,同时改变大小。基本上,它是一种“鱼眼”效果,当照片向窗口中心移动时,照片变大,然后在移开时缩小回原来的大小。
在任何给定时间,窗口将只显示3张照片(加上左边窗口的1张照片)。假设从左到右排列的3张照片标记为P1,P2,P3。考虑一张照片,最右边的照片P3。当P3从窗口右侧向中心移动时,其尺寸应逐渐增大并在窗口中心达到最大尺寸。当它继续向左移动并最终退出窗口时,其大小应该减小回原始值。
如果我只是在不调整照片大小的情况下移动照片,那么我当前的实现是有效的。当同时移动和缩放图像时,照片不再水平移动穿过窗口的中心。照片的大小似乎可以正确缩放。
我当前的实现依赖于QPropertyAnimation类来执行动画。我正在使用Python和Qt的PySide绑定编写程序,但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正在应用于翻译的照片,从而影响其轨迹,但我可能错了,因为我刚开始使用Qt过去1-2周。
有谁知道如何让QPropertyAnimation知道另一个动画正在发生?或者,任何人都可以建议采用不同的方法(不一定涉及QPropertyAnimation)来解决上述问题吗?
预先感谢任何回复。
答案 0 :(得分:0)
我假设您正在使用QGraphicsView框架(如果您发布了一个最小的,正在运行的示例程序,那么理解和调试您的问题会更容易。)
我建议使用QGraphicsWidgets并直接为"geometry" property制作动画(编辑:我在这里错了,这不行)。
您需要在不使用两个QPropertyAnimations的情况下同时更改大小和位置。最可能最简单的解决方案是子类一个QVariantAnimation(甚至是QVariantAnimation)并适当地实现updateCurrentValue()
。我想我会插入一个QRectF,你可以从中提取位置和大小/比例,否则你当然可以插入一个浮点数(这意味着你可以有更多的插值代码来自己做,但是它需要计算从尺寸)。考虑将所需的比例编组到QRectF的大小(例如,将QSizeF(scale, scale)
传递给构造函数)。这有点hackish,因为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”属性的实现;如果转换相互作用(我会考虑不受欢迎的行为),那就是原因。