使用 QPropertyAnimation 的线条动画

Line Animation with QPropertyAnimation

尝试使用 PyQt5 和 QPropertyAnimation 为一条从无到有 (0,0) 到 (200, 200) 的线设置动画。我已经阅读了很多关于 Qt 的文档并尝试了几个示例,但我就是无法让它工作。这是我现在的代码:

from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
from PyQt5.QtGui import QPainter, QPixmap, QPainterPath
from PyQt5.QtCore import QObject, QPointF, QPropertyAnimation, pyqtProperty
from PyQt5.QtCore import QLineF
import sys


class Sample(QWidget):

    l1 = QLineF(QPointF(), QPointF())

    def __init__(self):
        super().__init__()

        self.initView()
        self.initAnimation()

    def initView(self):    
        self.show()

    def initAnimation(self):
        self.anim = QPropertyAnimation(self.l1, b'geometry')
        self.anim.setDuration(7000)
        self.anim.setStartValue(QPointF(0, 0))
        self.anim.setEndValue(QPointF(200, 200))
        self.anim.start()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Sample()
    sys.exit(app.exec_())

没有发布所有以前的尝试,每次都失败并出现不同的错误。我在一个小部件上有一个淡出动画可以工作,还有一张图片沿着一条路径,但我似乎可以画一个简单的线条图。我希望实现这样的目标:

Codepen example

Qt 文档很庞大,似乎有几种方法可以实现这一点,画家和计时器、动画、变体动画,但我对 C++ 不是很熟悉,翻译成 Python 并不总是那么容易.样品也不是那么容易找到。

我是否漏掉了一些明显的东西?

谢谢!


郑重声明,这是我目前所取得的成就,但是一旦我取消对 QPropertyAnimation 创建的注释,应用程序就不会启动。无论如何,我离接受的答案还差得很远。

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

class MyLine(QGraphicsLineItem, QObject):
    def __init__(self):
        super().__init__()

    def _set_start(self, point):
        self.setLine(point.x(), point.y(), self.line().p2().x(), self.line().p2().y())

    def _set_end(self, point):
        self.setLine(self.line().p1().x(), self.line().p1().y(), point.x(), point.y())

    start = pyqtProperty(QPointF, fset=_set_start)
    end = pyqtProperty(QPointF, fset=_set_end)


class Example(QWidget):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        hbox = QHBoxLayout(self)

        self.button = QPushButton("Start", self)
        self.button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        hbox.addWidget(self.button)

        hbox.addSpacing(40)

        self.line = MyLine()
        self.line.setLine(0, 0, 10, 10)
        scene = QGraphicsScene()
        scene.addItem(self.line)
        view = QGraphicsView(scene)
        hbox.addWidget(view)

        self.anim = QPropertyAnimation(self.line, b"end") # crash without error here
        # self.anim.setDuration(2500)
        # self.anim.setLoopCount(1)
        # self.anim.setStartValue(QPointF(10, 10))
        # self.anim.setEndValue(QPointF(200, 200))
        # self.button.clicked.connect(self.anim.start)

        self.setGeometry(300, 300, 380, 250)
        self.setWindowTitle('Color anim')
        self.show()


if __name__ == "__main__":

    app = QApplication([])
    ex = Example()
    ex.show()
    app.exec_()

您必须使用 QGraphicsView、QGraphicsScene 和 QGraphicsLineItem,如下所示:

from PyQt5 import QtCore, QtGui, QtWidgets


class LineAnimation(QtCore.QObject):
    def __init__(self, parent=None):
        super(LineAnimation, self).__init__(parent)
        self.m_line = QtCore.QLineF()
        self.m_item = QtWidgets.QGraphicsLineItem()
        self.m_item.setLine(self.m_line)
        self.m_item.setPen(
            QtGui.QPen(
                QtGui.QColor("salmon"),
                10,
                QtCore.Qt.SolidLine,
                QtCore.Qt.SquareCap,
                QtCore.Qt.RoundJoin,
            )
        )

        self.m_animation = QtCore.QPropertyAnimation(
            self,
            b"p2",
            parent=self,
            startValue=QtCore.QPointF(0, 0),
            endValue=QtCore.QPointF(200, 200),
            duration=5 * 1000,
        )
        self.m_animation.start()

    def p1(self):
        return self.m_line.p1()

    def setP1(self, p1):
        self.m_line.setP1(p1)
        self.m_item.setLine(self.m_line)

    def p2(self):
        return self.m_line.p2()

    def setP2(self, p2):
        self.m_line.setP2(p2)
        self.m_item.setLine(self.m_line)

    p1 = QtCore.pyqtProperty(QtCore.QPointF, fget=p1, fset=setP1)
    p2 = QtCore.pyqtProperty(QtCore.QPointF, fget=p2, fset=setP2)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        scene = QtWidgets.QGraphicsScene(self)
        view = QtWidgets.QGraphicsView(
            scene, alignment=QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop
        )
        self.setCentralWidget(view)

        line_animation = LineAnimation(self)
        scene.addItem(line_animation.m_item)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())