Как запустить анимацию для нескольких обьектов в PyQT5?

По задумке код ниже должен запускать анимации для 2 обьектов le и le1, но двигается только le1

from PyQt5.QtWidgets import QWidget, QApplication, QLabel
from PyQt5.QtCore import Qt, QPropertyAnimation, QRect

class Dialog(QWidget):
    def __init__(self):
        super().__init__()
        self.x = 300  # позиция по оси x
        self.y = 300  # позиция по оси y
        self.w = 300  # ширина
        self.h = 220  # высота
    self._geometry = [self.x, self.y, self.w, self.h]

    self.setWindowTitle('Dialog')  # имя Title
    self.setGeometry(*self._geometry)  # Геометрия

    self.le = QLabel('this', self)
    self.le.move(110, 30)
    self.le1 = QLabel('this', self)
    self.le1.move(200, 30)

    self.lees = [self.le, self.le1]
    for n in range(len(self.lees)):
        i = self.lees[n]
        x = i.pos().x()
        y = i.pos().y()
        print(i, x, y)
        self.animation = QPropertyAnimation(i, b'geometry')
        self.animation.setStartValue(QRect(x, y, 100, 30))
        self.animation.setEndValue(QRect(x, y + 200, 100, 30))
        self.animation.setLoopCount(1)
        self.animation.setDuration(5000)
        self.animation.start()


if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    w = Dialog()
    w.show()
    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

QPropertyAnimation работает как шарм сам по себе. Для сложных анимаций, которые, например, содержат несколько объектов, предоставляется QAnimationGroup.

Группа анимации - это анимация, которая может содержать другие анимации и может управлять воспроизведением ее анимации. Взгляните на QParallelAnimationGroup для примера.

from PyQt5.QtWidgets import QWidget, QApplication, QLabel
from PyQt5.QtCore import Qt, QPropertyAnimation, QRect, QParallelAnimationGroup

class Dialog(QWidget):
    def __init__(self):
        super().__init__()
        self.x = 300  # позиция по оси x
        self.y = 300  # позиция по оси y
        self.w = 300  # ширина
        self.h = 320  # высота
        
        self._geometry = [self.x, self.y, self.w, self.h]

        self.setWindowTitle('Dialog')  # имя Title
        self.setGeometry(*self._geometry)  # Геометрия

        self.le = QLabel('this le', self)
        self.le.move(110, 30)
        self.le1 = QLabel('this le1', self)
        self.le1.move(200, 30)

        self.lees = [self.le, self.le1]
        
        animation1 = QPropertyAnimation(self.lees[0], b'geometry')
        animation2 = QPropertyAnimation(self.lees[1], b'geometry')
        
        group = QParallelAnimationGroup(self)                # Паралельная анимациия            
        group.addAnimation(animation1)
        group.addAnimation(animation2)

        animation1.setStartValue(QRect(self.lees[0].pos().x(), self.lees[0].pos().y(), 100, 30))
        animation1.setEndValue(QRect(self.lees[0].pos().x(), self.lees[0].pos().y() + 200, 100, 30))
        animation1.setLoopCount(1)
        animation1.setDuration(5000)

        animation2.setStartValue(QRect(self.lees[1].pos().x(), self.lees[1].pos().y(), 100, 30))
        animation2.setEndValue(QRect(self.lees[1].pos().x(), self.lees[1].pos().y() + 200, 100, 30))
        animation2.setLoopCount(1)
        animation2.setDuration(5000)

        group.start()


if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    w = Dialog()
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения


Update

А можно ли как то запустить их по отдельности? Допустим у le уже идет анимация, и спустя полсекунды запускается анимация у le1 ?

QSequentialAnimationGroup выполняет анимацию последовательно, в то время как QParallelAnimationGroup выполняет все анимации, добавленные в группу одновременно.

Но вы можете поиграться с типами кривой плавности. enum QEasingCurve::Type читаем здесь https://doc.qt.io/qt-5/qeasingcurve.html#Type-enum

Также вы можете задавать различные значения setDuration, чтобы добиться нужного вам эффекта. Попробуйте :

from PyQt5.QtWidgets import QWidget, QApplication, QLabel
from PyQt5.QtCore import Qt, QPropertyAnimation, QRect, QParallelAnimationGroup, QEasingCurve

class Dialog(QWidget):
    def __init__(self):
        super().__init__()
        self.x = 300  # позиция по оси x
        self.y = 300  # позиция по оси y
        self.w = 300  # ширина
        self.h = 320  # высота
        
        self._geometry = [self.x, self.y, self.w, self.h]

        self.setWindowTitle('Dialog')  # имя Title
        self.setGeometry(*self._geometry)  # Геометрия

        self.le = QLabel('this le', self)
        self.le.move(110, 30)
        self.le1 = QLabel('this le1', self)
        self.le1.move(200, 30)

        self.lees = [self.le, self.le1]
        
        animation1 = QPropertyAnimation(self.lees[0], b'geometry')
        animation2 = QPropertyAnimation(self.lees[1], b'geometry')
        
        group = QParallelAnimationGroup(self)                # Паралельная анимациия            
        group.addAnimation(animation1)
        group.addAnimation(animation2)

        animation1.setStartValue(QRect(self.lees[0].pos().x(), self.lees[0].pos().y(), 100, 30))
        animation1.setEndValue(QRect(self.lees[0].pos().x(), self.lees[0].pos().y() + 200, 100, 30))
        animation1.setLoopCount(1)
        animation1.setDuration(5000)
        animation1.setEasingCurve(QEasingCurve.OutBounce)                # +++

        animation2.setStartValue(QRect(self.lees[1].pos().x(), self.lees[1].pos().y(), 100, 30))
        animation2.setEndValue(QRect(self.lees[1].pos().x(), self.lees[1].pos().y() + 200, 100, 30))
        animation2.setLoopCount(1)
        animation2.setDuration(8000)                                      # 8000
        animation2.setEasingCurve(QEasingCurve.CosineCurve)               # +++

        group.start()


if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    w = Dialog()
    w.show()
    sys.exit(app.exec_())
→ Ссылка