from PySide6.QtWidgets import QApplication, QPushButton, QMainWindow from PySide6.QtCore import QPropertyAnimation, QPoint, QParallelAnimationGroup, QEasingCurve, Property from PySide6.QtGui import QColor, QPainter, QBrush from PySide6.QtCore import Qt import sys class RippleButton(QPushButton): def __init__(self, text, parent=None): super().__init__(text, parent) self._ripple_radius = 0 self._ripple_opacity = 1.0 self.ripple_position = QPoint() self.animation_group = QParallelAnimationGroup(self) # 设置父对象 self.setStyleSheet("background-color: #3498db; color: white; border-radius: 5px; padding: 10px;") self.setAttribute(Qt.WA_StaticContents) def paintEvent(self, event): super().paintEvent(event) if self._ripple_radius > 0: painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) color = QColor(255, 255, 255) color.setAlphaF(self._ripple_opacity) painter.setBrush(QBrush(color)) painter.setPen(Qt.NoPen) painter.drawEllipse(self.ripple_position, self._ripple_radius, self._ripple_radius) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.ripple_position = event.pos() self.startRippleEffect() super().mousePressEvent(event) def startRippleEffect(self): # 取消之前的动画 self.animation_group.stop() self.animation_group.clear() # 创建半径动画 radius_animation = QPropertyAnimation(self, b"rippleRadius") radius_animation.setDuration(600) radius_animation.setStartValue(0) # 计算最大半径,确保覆盖按钮 max_radius = max(self.width(), self.height()) * 1.5 radius_animation.setEndValue(max_radius) radius_animation.setEasingCurve(QEasingCurve.OutQuad) # 创建透明度动画 opacity_animation = QPropertyAnimation(self, b"rippleOpacity") opacity_animation.setDuration(600) opacity_animation.setStartValue(0.5) # 初始透明度可以调整 opacity_animation.setEndValue(0.0) opacity_animation.setEasingCurve(QEasingCurve.OutQuad) # 将动画添加到动画组 self.animation_group.addAnimation(radius_animation) self.animation_group.addAnimation(opacity_animation) self.animation_group.start() # 使用 @Property 装饰器正确定义属性 def getRippleRadius(self): return self._ripple_radius def setRippleRadius(self, radius): self._ripple_radius = radius self.update() rippleRadius = Property(float, getRippleRadius, setRippleRadius) def getRippleOpacity(self): return self._ripple_opacity def setRippleOpacity(self, opacity): self._ripple_opacity = opacity self.update() rippleOpacity = Property(float, getRippleOpacity, setRippleOpacity) class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("水滴扩散按钮示例") self.setFixedSize(400, 300) self.button = RippleButton("点击我", self) self.button.setGeometry(150, 130, 100, 40) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec())