如何在QStyledItemDelegate的paint方法中实现QRect的10秒渐隐动画
解决方案
你没法直接在paint方法里集成QPropertyAnimation是对的——paint是被动触发的重绘回调,本身没有持续运行的上下文,而且Delegate是多个条目复用的实例,也没法为单个条目绑定动画属性。按下面的方案改就行:
第一步:补充数据存储逻辑
在你每条数据对应的条目类里,新增两个字段,用来记录淡出的触发状态:
- 当
attr_X被设置为True的同时,记录当前的时间戳到fade_start_ms字段,未触发时设为None - 固定淡出时长为
10 * 1000(10秒,单位毫秒)
如果不方便修改条目类结构,也可以在Delegate内部维护一个字典,用条目的唯一标识当key,存对应的触发时间。
第二步:给Delegate加全局刷新定时器
在Delegate的初始化方法里加一个定时刷新的定时器,定时触发视图重绘:
from PyQt5 import QtCore, QtGui, QtWidgets class YourDelegate(QtWidgets.QStyledItemDelegate): def __init__(self, parent=None): super().__init__(parent) self.font = QtGui.QFont() self.normalPen = QtGui.QPen() # 新增定时器,每40毫秒刷新一次(对应25帧,足够流畅) self.refresh_timer = QtCore.QTimer(self) self.refresh_timer.setInterval(40) self.refresh_timer.timeout.connect(self.parent().viewport().update) self.refresh_timer.start()
第三步:修改paint方法计算透明度
在paint方法里实时计算当前条目的透明度,带透明度绘制矩形:
def paint(self, painter, option, index): painter.save() painter.setFont(self.font) painter.setPen(self.normalPen) r = option.rect.adjusted(5, 0, -5, 0) item = index.model().sourceModel().rowData(index.model().mapToSource(index)) if item.attr_X is True and hasattr(item, 'fade_start_ms') and item.fade_start_ms is not None: # 计算已流逝的时间 current_ms = QtCore.QDateTime.currentMSecsSinceEpoch() elapsed_ms = current_ms - item.fade_start_ms fade_duration = 10 * 1000 # 10秒 if elapsed_ms < fade_duration: # 计算透明度:从255降到0 alpha = 255 * (1 - elapsed_ms / fade_duration) fill_color = QtGui.QColor(100, 100, 100, int(alpha)) painter.fillRect(option.rect, QtGui.QBrush(fill_color)) # 超过10秒就不绘制,相当于完全消失 # 原来的其他绘制逻辑放这里 painter.restore()
可选优化
- 如果很多条目都已经完成淡出,可以加逻辑判断当前可见条目里还有没有正在动画的,没有就暂时停掉定时器,减少不必要的重绘消耗。
- 如果用Delegate内部字典存触发时间,记得在条目删除时同步清理对应key,避免内存泄漏。
内容的提问来源于stack exchange,提问作者John D.
相关产品推荐
相关产品推荐

