Files
nl-tools/ui/animations.py

184 lines
5.4 KiB
Python
Raw Permalink Normal View History

2025-12-11 09:47:00 +08:00
"""
UI动画效果模块
- 渐入渐出
- 滑动效果
- 缩放效果
"""
from PySide6.QtWidgets import QWidget, QGraphicsOpacityEffect
from PySide6.QtCore import (
QPropertyAnimation, QEasingCurve, QParallelAnimationGroup,
QSequentialAnimationGroup, Property, QPoint, QSize
)
from PySide6.QtGui import QColor
from core.config import config
class AnimationMixin:
"""动画混入类,为QWidget添加动画功能"""
def setup_animation(self):
"""初始化动画效果"""
if not hasattr(self, '_opacity_effect'):
self._opacity_effect = QGraphicsOpacityEffect(self)
self._opacity_effect.setOpacity(1.0)
self.setGraphicsEffect(self._opacity_effect)
def fade_in(self, duration: int = None, callback=None):
"""渐入动画"""
if not config.get("animation_enabled", True):
if callback:
callback()
return
self.setup_animation()
duration = duration or config.get("animation_duration", 300)
self._opacity_effect.setOpacity(0)
self.show()
self._fade_anim = QPropertyAnimation(self._opacity_effect, b"opacity")
self._fade_anim.setDuration(duration)
self._fade_anim.setStartValue(0.0)
self._fade_anim.setEndValue(1.0)
self._fade_anim.setEasingCurve(QEasingCurve.Type.OutCubic)
if callback:
self._fade_anim.finished.connect(callback)
self._fade_anim.start()
def fade_out(self, duration: int = None, callback=None):
"""渐出动画"""
if not config.get("animation_enabled", True):
self.hide()
if callback:
callback()
return
self.setup_animation()
duration = duration or config.get("animation_duration", 300)
self._fade_anim = QPropertyAnimation(self._opacity_effect, b"opacity")
self._fade_anim.setDuration(duration)
self._fade_anim.setStartValue(1.0)
self._fade_anim.setEndValue(0.0)
self._fade_anim.setEasingCurve(QEasingCurve.Type.InCubic)
def on_finished():
self.hide()
self._opacity_effect.setOpacity(1.0)
if callback:
callback()
self._fade_anim.finished.connect(on_finished)
self._fade_anim.start()
def create_fade_animation(widget: QWidget, fade_in: bool = True, duration: int = None) -> QPropertyAnimation:
"""创建渐变动画"""
if not config.get("animation_enabled", True):
return None
duration = duration or config.get("animation_duration", 300)
# 确保有透明度效果
effect = widget.graphicsEffect()
if not isinstance(effect, QGraphicsOpacityEffect):
effect = QGraphicsOpacityEffect(widget)
widget.setGraphicsEffect(effect)
anim = QPropertyAnimation(effect, b"opacity")
anim.setDuration(duration)
if fade_in:
anim.setStartValue(0.0)
anim.setEndValue(1.0)
anim.setEasingCurve(QEasingCurve.Type.OutCubic)
else:
anim.setStartValue(1.0)
anim.setEndValue(0.0)
anim.setEasingCurve(QEasingCurve.Type.InCubic)
return anim
def create_slide_animation(widget: QWidget, start_pos: QPoint, end_pos: QPoint,
duration: int = None) -> QPropertyAnimation:
"""创建滑动动画"""
if not config.get("animation_enabled", True):
widget.move(end_pos)
return None
duration = duration or config.get("animation_duration", 300)
anim = QPropertyAnimation(widget, b"pos")
anim.setDuration(duration)
anim.setStartValue(start_pos)
anim.setEndValue(end_pos)
anim.setEasingCurve(QEasingCurve.Type.OutCubic)
return anim
def animate_widget_show(widget: QWidget, direction: str = "fade"):
"""显示控件动画"""
if not config.get("animation_enabled", True):
widget.show()
return
duration = config.get("animation_duration", 300)
if direction == "fade":
effect = QGraphicsOpacityEffect(widget)
effect.setOpacity(0)
widget.setGraphicsEffect(effect)
widget.show()
anim = QPropertyAnimation(effect, b"opacity")
anim.setDuration(duration)
anim.setStartValue(0.0)
anim.setEndValue(1.0)
anim.setEasingCurve(QEasingCurve.Type.OutCubic)
anim.start()
# 保持引用
widget._show_anim = anim
else:
widget.show()
def animate_widget_hide(widget: QWidget, callback=None):
"""隐藏控件动画"""
if not config.get("animation_enabled", True):
widget.hide()
if callback:
callback()
return
duration = config.get("animation_duration", 300)
effect = widget.graphicsEffect()
if not isinstance(effect, QGraphicsOpacityEffect):
effect = QGraphicsOpacityEffect(widget)
widget.setGraphicsEffect(effect)
anim = QPropertyAnimation(effect, b"opacity")
anim.setDuration(duration)
anim.setStartValue(1.0)
anim.setEndValue(0.0)
anim.setEasingCurve(QEasingCurve.Type.InCubic)
def on_finished():
widget.hide()
effect.setOpacity(1.0)
if callback:
callback()
anim.finished.connect(on_finished)
anim.start()
# 保持引用
widget._hide_anim = anim