使用QPropertyAnimation实现QGraphicsPathItem颜色动画时创建Edge类崩溃求助
QGraphicsPathItem颜色动画实现与崩溃修复
实现QGraphicsPathItem的颜色动画效果,需按照Qt官方文档「图形视图框架的动画机制」章节的指引完成子类化定制。
当需要对QGraphicsItem应用动画效果时,同样可以使用QPropertyAnimation实现。但需注意,QGraphicsItem本身并不继承QObject,可行的解决思路是对需要做动画的图形项进行子类化,让该自定义类同时继承QObject,这样即可将QPropertyAnimation应用于QGraphicsItem,后续示例将演示具体实现方式;另一种可选方案是直接继承本身已属于QObject子类的QGraphicsWidget。
注意:由于Qt元对象系统的要求,继承关系中QObject必须作为第一个被继承的类。
按照上述文档要求编写集成QObject的自定义Edge类后,创建Edge类实例时程序直接崩溃,原始代码如下:
class Edge(QObject, QGraphicsPathItem): def __init__(self, point1, point2): super().__init__() self.point1 = point1 self.point2 = point2 self.setPen(QPen(Qt.white, 2, Qt.SolidLine)) def create_path(self, radius): path = QPainterPath() path.moveTo(self.point1.x() + radius, self.point1.y() + radius) path.lineTo(self.point2.x() + radius, self.point2.y() + radius) return path
崩溃根因
- 代码中仅通过单次
super().__init__()完成初始化,按照Python的方法解析顺序,该调用仅会触发排在第一位的QObject类的构造逻辑,完全没有执行QGraphicsPathItem的初始化流程 - 图形项的底层渲染相关成员未完成初始化,后续调用
setPen等图形项原生方法时,会直接触发段错误导致程序崩溃
修正后的可运行实现
- 多继承场景下不依赖无参
super()跨调用父类构造,需显式分别调用两个父类的初始化方法,确保两个基类的逻辑都被完整执行 - 实现供
QPropertyAnimation绑定的颜色属性接口,打通动画驱动的属性更新链路
from PyQt6.QtCore import QObject, pyqtProperty, QPropertyAnimation, QEasingCurve, Qt from PyQt6.QtGui import QPen, QPainterPath, QColor from PyQt6.QtWidgets import QGraphicsPathItem class Edge(QObject, QGraphicsPathItem): def __init__(self, point1, point2): # 显式完成两个父类的初始化,避免逻辑遗漏 QObject.__init__(self) QGraphicsPathItem.__init__(self) self.point1 = point1 self.point2 = point2 self.setPen(QPen(Qt.GlobalColor.white, 2, Qt.PenStyle.SolidLine)) # 定义可被动画系统识别的线条颜色属性 @pyqtProperty(QColor) def line_color(self): return self.pen().color() @line_color.setter def line_color(self, color): current_pen = self.pen() current_pen.setColor(color) self.setPen(current_pen) def create_path(self, radius): path = QPainterPath() path.moveTo(self.point1.x() + radius, self.point1.y() + radius) path.lineTo(self.point2.x() + radius, self.point2.y() + radius) self.setPath(path) return path def start_color_anim(self, target_color, duration=1000): anim = QPropertyAnimation(self, b"line_color") anim.setDuration(duration) anim.setStartValue(self.line_color) anim.setEndValue(target_color) anim.setEasingCurve(QEasingCurve.Type.InOutSine) # 将动画对象绑定到实例上,避免被垃圾回收导致动画中断 self._anim = anim anim.start()
内容的提问来源于stack exchange,提问作者sirbuandrei
相关产品推荐
相关产品推荐

