简体   繁体   English

PyQt5 animation 行为作为 class 属性

[英]PyQt5 animation behaviour as class attribute

I made a mini-game with python and pyqt5, a moving box that you can move with the arrow keys, but the animation only works when it is defined as a class attribute. I made a mini-game with python and pyqt5, a moving box that you can move with the arrow keys, but the animation only works when it is defined as a class attribute.

Here is the code:这是代码:

    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

When I replace animation with self.animation, it works fine.当我用 self.animation 替换 animation 时,它工作正常。 I don't have a problem using self.animation, but it took me some time to realize that the reason my code wasn't working is because it's not an attribute, why does animation only works when it's an attribute?我使用 self.animation 没有问题,但我花了一些时间才意识到我的代码不起作用的原因是因为它不是一个属性,为什么 animation 只有在它是一个属性时才有效?

The problem is that "animation" is a local variable so it will be eliminated when the function that created it finishes executing, in your case when it finishes executing "move" that is an instant after starting the animation.问题是“动画”是一个局部变量,因此当创建它的 function 完成执行时,它将被消除,在您的情况下,当它完成执行“移动”时,即启动 animation 后的瞬间。

To understand this we can use the following example, because QPropertyAnimation is a QObject, it has the destroyed signal that indicates when a QObject is destroyed.为了理解这一点,我们可以使用以下示例,因为 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_())

Output: Output:

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

So the solution in general is that it is not eliminated at least until the animation ends, for this there are several options:所以一般的解决方案是至少在 animation 结束之前不会消除它,为此有几个选项:

  1. Make it an attribute of the class since it will have the same life cycle as the class, and that is the method you used.使其成为 class 的属性,因为它将具有与 class 相同的生命周期,这就是您使用的方法。

  2. Since QPropertyAnimation is a QObject, then one way to extend the life cycle is to pass it a parent, but in this case it is better to destroy it as soon as the animation is finished:由于 QPropertyAnimation 是一个 QObject,那么延长生命周期的一种方法是将其传递给父级,但在这种情况下,最好在 animation 完成后立即销毁它:

def move(self, direction):
    animation = QPropertyAnimation(self.box, b'geometry', parent=self)
    # ...
    animation.start(QPropertyAnimation.DeleteWhenStopped)
    animation.finished.connect(lambda: self.move(direction))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM