Поведение анимации PyQt5 как атрибут класса - PullRequest
1 голос
/ 24 сентября 2019

Я сделал мини-игру с python и pyqt5, движущимся боксом, который вы можете перемещать с помощью клавиш со стрелками, но анимация работает только тогда, когда она определена как атрибут класса.

Вот код:

    class Game(QMainWindow):
        # some code
        def move(self, direction):
            animation = QPropertyAnimation(self.box, b'geometry')
            x, y = self.box.x(), self.box.y()
            if(direction=='right'):
                x+=10
            # directions left, up and down
            animation.setEndValue(QRect(x, y, 20, 20))
            box.move(x, y)
            animation.setDuration(20)
            animation.start()
            animation.finished.connect(lambda: self.move(direction)
        # capture keypress to move the box

Когда я заменяю анимацию на self.animation, она работает нормально.У меня нет проблем с использованием self.animation, но мне потребовалось некоторое время, чтобы понять, что причина, по которой мой код не работает, заключается в том, что это не атрибут, почему анимация работает только тогда, когда это атрибут?

1 Ответ

0 голосов
/ 24 сентября 2019

Проблема в том, что «анимация» является локальной переменной, поэтому она будет исключена, когда завершит выполнение создавшая ее функция, в вашем случае, когда она завершит выполнение «перемещения», которое является мгновенным после запуска анимации.

Чтобы понять это, мы можем использовать следующий пример, поскольку QPropertyAnimation является объектом QObject, у него есть сигнал уничтожения, который указывает, когда уничтожается объект QObject.

import sys

from PyQt5 import QtCore, QtGui, QtWidgets


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.box = QtWidgets.QPushButton("QPushButton", self)

    def move(self, pos):
        animation = QtCore.QPropertyAnimation(self.box, b"pos")
        animation.setStartValue(self.box.pos())
        animation.setEndValue(pos)
        animation.setDuration(20)
        animation.start()
        animation.destroyed.connect(lambda obj: print("destroyed", obj))


if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    w.move(QtCore.QPoint(40, 40))
    sys.exit(app.exec_())

Вывод:

destroyed <PyQt5.QtCore.QObject object at 0x7f412abffd70>

Таким образом, решение в целом состоит в том, что оно не устраняется, по крайней мере, до окончания анимации, для этого есть несколько вариантов:

  1. Сделать его атрибутом класса, так каку него будет тот же жизненный цикл, что и у класса, и этот метод вы использовали.

  2. Поскольку QPropertyAnimation является объектом QObject, то один из способов продлить жизненный цикл - передать емуродитель, но в этом случае лучше уничтожить его, как только анимация закончится:

def move(self, direction):
    animation = QPropertyAnimation(self.box, b'geometry', <b>parent=self</b>)
    # ...
    animation.start(<b>QPropertyAnimation.DeleteWhenStopped</b>)
    animation.finished.connect(lambda: self.move(direction))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...