首页 > 解决方案 > 将动画对象附加到列表时不发生动画

问题描述

我在我的应用程序中创建了两个框架和一个按钮,我想在按下该按钮时动画调整框架的大小。我创建了两个函数*(应该工作相同)* 用于动画帧,*(参见下面的代码)*。

如果您按原样运行代码,它将按照我的意愿为框架设置动画,但如果您使用第二个函数 *(我已将其注释掉)*,它将不起作用。我不知道为什么?有人可以解释一下吗。如果可能的话,一个解决方案。

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys


class Test(QMainWindow):
    
    def __init__(self):
        super().__init__()
        self.resize(500, 500)
        self.frame_to_animate()


    # Creating items for the app
    def frame_to_animate(self):
        self.widget = QWidget()
        self.setCentralWidget(self.widget)

        # Frame to animate 1
        self.frame = QFrame(self.widget)
        self.frame.setStyleSheet('QFrame {background: red}')
        self.frame.resize(100, 100)
        
        # Frame to animate 2
        self.frame2 = QFrame(self.widget)
        self.frame2.move(0, 250)
        self.frame2.setStyleSheet('QFrame {background: yellow}')
        self.frame2.resize(100, 100)
        
        self.thing = False

        # Button to animate the frame
        self.btn = QPushButton(self.widget)
        self.btn.setText('Animate the frame')
        self.btn.move(300, 200)
        self.btn.clicked.connect(self.animation_fctn)
        # self.btn.clicked.connect(self.anim_fctn_i_want)           # This animation should be working
        
    
    # I want this way to work, but it's not working        
    def anim_fctn_i_want(self):
        anim_list = []
        for item in [self.frame, self.frame2]:
            anim_list.append(QPropertyAnimation(item, b"size"))
        
        for anim in anim_list:
            anim.setDuration(1000)
            if self.thing is False:
                anim.setEndValue(QSize(200, 200))
                self.thing = True
            else:
                anim.setEndValue(QSize(100, 100))
                self.thing = False
            anim.start()
            
            
    # Creating Animation one by one
    def animation_fctn(self):
        self.anim = QPropertyAnimation(self.frame, b"size")
        self.anim2 = QPropertyAnimation(self.frame2, b"size")
        
        self.anim.setDuration(1000)
        self.anim2.setDuration(1000)
        
        if self.thing is False:
            self.anim.setEndValue(QSize(200, 200))
            self.anim2.setEndValue(QSize(200, 200))
            self.thing = True
            
        else:
            self.anim.setEndValue(QSize(100, 100))
            self.anim2.setEndValue(QSize(100, 100))
            self.thing = False
            
        self.anim.start()
        self.anim2.start()
    
    
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Test()
    window.show()
    app.exec()

我目前的方法*(工作正常)*的问题是我必须手动为每个项目执行此操作,并且在我的原始代码中,由于项目很多,它会很麻烦,

第二种方法会使它变得简单,但它不起作用。尝试代码,请指出我做错了什么。

首先尝试一下。然后用# self.btn.clicked.connect(self.anim_fctn_i_want) # This animation should be working

标签: pythonanimationpyqtpyqt5

解决方案


问题是在这种情况下,动画的范围仅限于列表的范围,而列表是一个变量,会立即被消除,因此动画也是如此,所以看不到它们的效果。解决方案是延长动画的生命周期,为此有几个选项,例如使列表成为类的属性或将父级传递给动画,因为它们是 QObjects,在这种情况下将使用第二个:

def anim_fctn_i_want(self):
    for item in (self.frame, self.frame2):
        anim = QPropertyAnimation(item, b"size", parent=item)
        anim.setDuration(1000)
        anim.setEndValue(QSize(100, 100) if self.thing else QSize(200, 200))
        anim.start(QAbstractAnimation.DeleteWhenStopped)
    self.thing = not self.thing

另一方面,如果您要并行处理多个动画,那么出于性能原因,最好使用 QParallelAnimationGroup:

def anim_fctn_i_want(self):
    group_animation = QParallelAnimationGroup(self)
    for item in (self.frame, self.frame2):
        anim = QPropertyAnimation(item, b"size")
        anim.setDuration(1000)
        anim.setEndValue(QSize(100, 100) if self.thing else QSize(200, 200))
        group_animation.addAnimation(anim)
    group_animation.start(QAbstractAnimation.DeleteWhenStopped)
    self.thing = not self.thing

推荐阅读