0

我正在寻找一种解决方案,从 0 到 360° 为这条弧设置动画。我对 Pyside/Pyqt 比较陌生,我找不到这么简单的解决方案(只有初学者“不友好”)。我也尝试过使用 while 循环,但它不起作用。目前我不了解这个动画系统,但我想研究它。

import sys

from PySide6 import QtCore
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtCore import Qt
from PySide6.QtGui import QBrush, QPen, QPainter


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowTitle("AnimateArc")
        self.setGeometry(100, 100, 600, 600)

    def paintEvent(self, event):
        self.anim = QtCore.QPropertyAnimation(self, b"width", duration=1000) #<- is there a documentation for b"width", b"geometry"?
        self.anim.setStartValue(0)
        start = 0
        painter = QPainter(self)
        painter.setPen(QPen(Qt.black, 5, Qt.SolidLine))
        painter.drawArc(100, 100, 400, 400, 90 * 16, start * 16)    # I want to make the change dynamicly

        self.anim.setEndValue(360)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    app.exec()
4

1 回答 1

1

QPropertyAnimation 用于为任何 QObject 的Qt 属性设置动画。如果您引用self(QMainWindow 的当前实例),那么您可以为 QMainWindow 的所有属性和所有继承的属性设置动画(QMainWindow 继承自 QWidget,因此您也可以为所有QWidget 属性设置动画)。
在您的情况下,您正在尝试为width窗口的属性设置动画,这当然不是您想要做的。

由于您要更改的是不是窗口属性的值,因此您不能使用 QPropertyAnimation(除非您使用@Property装饰器创建 Qt 属性),而应该使用 QVariantAnimation 代替。

然后,每次绘制小部件时,Qt 都会调用一个paintEvent (这可能经常发生),因此您不能在那里创建动画,否则您可能会以递归结束:因为动画需要重新绘制,每次上一个需要更新时,您都会创建一个新动画。

最后,考虑到通常不鼓励在 QMainWindow 上绘画,因为 Qt 主窗口是一种特殊的 QWidget,旨在用于高级功能(菜单、状态栏等)并使用中央小部件来显示实际内容。
正确的方法是创建和设置一个中央小部件,并在该小部件上实现绘画。

这是您的代码的修订版和工作版:

class ArcWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.anim = QtCore.QVariantAnimation(self, duration=1000)
        self.anim.setStartValue(0)
        self.anim.setEndValue(360)
        self.anim.valueChanged.connect(self.update)
        self.anim.start()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setPen(QPen(Qt.black, 5, Qt.SolidLine))
        painter.drawArc(
            100, 100, 400, 400, 90 * 16, self.anim.currentValue() * 16)


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowTitle("AnimateArc")
        self.setGeometry(100, 100, 600, 600)
        self.arcWidget = ArcWidget()
        self.setCentralWidget(self.arcWidget)

valueChanged连接确保每次值更改时,小部件都会安排更新(因此paintEvent只要事件队列允许就调用 a),然后您可以使用动画的当前值来绘制实际的弧线。

于 2021-06-06T13:39:30.190 回答