如何在pyqt5中缓慢移动标签?我希望标签自动移动(有一段时间为True吗?)

时间:2019-09-28 22:57:52

标签: python pyqt5

我想知道如何在pyqt5中缓慢移动标签,可以说标签是游戏的对象(箭头,子弹等),但标签必须在游戏的整个过程中自动移动

self.label_enemy = QLabel(self)
self.label_enemy.setGeometry(400, 50, 20, 20)
self.label_enemy.setStyleSheet("background-color: blue")
self.distancia_enemy = 4

1 个答案:

答案 0 :(得分:1)

您需要使用QPropertyAnimation,它允许您设置 target 对象的特定属性的动画开始和结束值。在您的情况下, target 是标签,而 property pos QProperty。

记住一些重要的事情:

  • 如果将小部件添加到布局中,则无法移动它(在下面的示例中,我使用的是“动画容器”小部件,其中包含要创建动画的对象);
  • properties个QObject(及其后代,包括QWidget)可以使用;这意味着您不能在不是QObject子类的对象上使用QPropertyAnimation;
  • 如果要设置对象未提供的其他任何属性的动画,则可以使用object.setProperty('propertyName', value)“创建”新属性,或使用QtCore.pyqtProperty decorator;
  • 对于硬编码位置要非常小心,如果包含动画的小部件可以更改其大小,那么您肯定会遇到一些问题(这就是为什么我在示例中使用固定大小的原因)
  • QGraphicsScene(及其可视化窗口小部件QGraphicsView)通常是一种更好的解决方案,例如您似乎对您感兴趣的动画,因为它们提供了高级的动画框架,该框架尤其有助于解决缩放问题和鼠标/键盘交互;不幸的是,他们需要一些高级技能和耐心才能理解和掌握。
from PyQt5 import QtCore, QtWidgets

class AnimationArea(QtWidgets.QWidget):
    def __init__(self):
        super(AnimationArea, self).__init__()
        self.setFixedSize(640, 480)
        self.enemy = QtWidgets.QLabel('X', self)
        self.enemyAnimation = QtCore.QPropertyAnimation(self.enemy, b'pos')
        # set a start value for the animation; if we don't provide this
        # the animation will use the end value as soon as it finishes.
        self.enemyAnimation.setStartValue(self.enemy.pos())
        # set an end value for the animation; this is always required.
        self.enemyAnimation.setEndValue(QtCore.QPoint(400, 200))
        self.enemyAnimation.setDuration(2000)

    def start(self):
        self.enemyAnimation.start()


class AniWindow(QtWidgets.QWidget):
    def __init__(self):
        super(AniWindow, self).__init__()
        layout = QtWidgets.QVBoxLayout()
        self.setLayout(layout)
        self.animationArea = AnimationArea()
        layout.addWidget(self.animationArea)
        self.startButton = QtWidgets.QPushButton('Start')
        layout.addWidget(self.startButton)
        self.startButton.clicked.connect(self.animationArea.start)


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    aniWindow = AniWindow()
    aniWindow.show()
    sys.exit(app.exec_())

对于更复杂的路径,有两种解决方案。

线性动画组

这使用QSequentialAnimationGroup来连接多个动画。优点是您可以为每个段设置不同的速度,但是始终为线性路径。由于动画是连续的(并且我们将在结尾处返回到开始位置),因此您只需要设置结束值即可。此摘要将使您的敌人绕三角形移动。

        self.enemyAnimation = QtCore.QSequentialAnimationGroup()
        first = QtCore.QPropertyAnimation(self.label_enemy, b'pos')
        first.setEndValue(QtCore.QPoint(0, 400))
        first.setDuration(1000)
        second = QtCore.QPropertyAnimation(self.label_enemy, b'pos')
        second.setEndValue(QtCore.QPoint(400, 400))
        second.setDuration(2000)
        third = QtCore.QPropertyAnimation(self.label_enemy, b'pos')
        third.setEndValue(QtCore.QPoint(0, 0))
        third.setDuration(3000)
        self.enemyAnimation.addAnimation(first)
        self.enemyAnimation.addAnimation(second)
        self.enemyAnimation.addAnimation(third)

遵循路径

QPainterPath可用于绘制更复杂(和非线性)的路径。对于这种方法,您需要使用从0.01.0的{​​{3}}和QVariantAnimation函数,该函数返回路径的任意百分比的坐标。在这种情况下,我使用了一条线段和一条曲线。

        self.enemyAnimation = QtCore.QVariantAnimation()
        # *BOTH* start and end values *HAVE* to be float!
        self.enemyAnimation.setStartValue(0.0)
        self.enemyAnimation.setEndValue(1.0)
        self.enemyAnimation.setDuration(2000)
        self.enemyPath = QtGui.QPainterPath()
        self.enemyPath.lineTo(100, 400)
        self.enemyPath.quadTo(400, 400, 400, 0)
        self.enemyAnimation.valueChanged.connect(self.moveEnemy)

    def moveEnemy(self, percent):
        self.label_enemy.move(self.enemyPath.pointAtPercent(percent).toPoint())