python - 使用 QPropertyAnimation 进行线条动画

标签 python animation pyqt pyqt5 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_())

关于python - 使用 QPropertyAnimation 进行线条动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56346883/

相关文章:

python - 如何使用Python将IOC文件转换为数据库条目?

python - 事件编辑器的 pydev 控制台路径

javascript - js 在 onLoad 中淡入淡出,for 循环、样式和 setInterval 不起作用?

python - PyQt4 初学者 - 无窗口图标

python - 如何在 PyQt4 QTreeWidget 的列单元格内绘制烛台条

python - 如何让 matplotlib.Figure() 接受 Drop 事件来绘制数据?

python - 写入CSV文件时,如何在Python中显示分组结果中的列名称?

Python:以比一秒更高分辨率获取文件修改时间

ios - 如何像 Viber 一样在我的 iOS 应用程序中播放 SVG 动画贴纸?

Python:使用 PIL 制作动画