UI 动画系统模块
QuModLibs.Modules.UI.Anims 提供 UI 控件动画托管能力。现代项目推荐使用 QAnimManager.bindRAIINode(...) 接入 ScreenNodeWrapper / QEScreenNode 的 RAII 生命周期,旧式手动 Tick 管理放在本文末尾,仅供维护历史项目参考。
现代推荐
优先使用 QAnimManager.bindRAIINode(uiNode)。它会在 UI 创建时自动监听帧事件,并在 UI 销毁时自动释放监听和动画对象。
QAnimManager 现代推荐
动画管理器用于统一托管多个控件的动画对象。通过 getControlAnimObj(path) 获取指定控件的 QAnimsControl 后,即可添加位置、大小、不透明度、打字机等动画变换。
# -*- coding: utf-8 -*-
from .QuModLibs.Client import *
from .QuModLibs.Modules.UI.EnhancedUI import QEScreenNode
from .QuModLibs.Modules.UI.Anims import QAnimManager, QPosTransform, QSizeTransform
@QEScreenNode.autoRegister("test_ui.main")
class TestUI(QEScreenNode):
def __init__(self, *args):
QEScreenNode.__init__(self, *args)
self.imgPath = "/panel/image"
self.animSystem = QAnimManager.bindRAIINode(self)
@QEScreenNode.OnClick("/panel/move")
def onMove(self):
animObj = self.animSystem.getControlAnimObj(self.imgPath)
animObj.changeTransformAnim(
QPosTransform(animObj.getPos(), (400, 100), useTime=0.8)
)
animObj.changeTransformAnim(
QSizeTransform(animObj.getScale(), animObj.controlInfo._baseScale, useTime=0.8, resizeChildren=True)
)使用条件
bindRAIINode 只能绑定到继承 QDRAIIEnv 的 UI 节点,例如 ScreenNodeWrapper / QEScreenNode。非 RAII 界面只能使用本文末尾的旧式绑定方式。
QAnimsControl
QAnimsControl 是单个控件的动画对象,通常不需要手动创建,而是通过 QAnimManager.getControlAnimObj(path) 获取。
常用方法
animObj = self.animSystem.getControlAnimObj("/panel/image")
animObj.addTransformAnim(QPosTransform(...))
animObj.changeTransformAnim(QSizeTransform(...))
animObj.removeTransformAnim(transformObj)
animObj.matchTransformWithClass(QPosTransform)
animObj.update(0.033, forceUpdate=True)addTransformAnim(transformObj):添加动画变换对象。changeTransformAnim(transformObj):添加动画,并覆盖同类型旧动画,通常比直接addTransformAnim更安全。removeTransformAnim(transformObj):移除指定动画对象。matchTransformWithClass(cls):查找当前控件上指定类型的动画对象,不存在时返回None。update(delayTime, forceUpdate=True):推进动画计算。使用QAnimManager时通常不需要手动调用。
注意事项
单个 QTransform 对象只能同时绑定到一个控件。需要复用动画配置时,请创建新的变换对象。
QTransform
QTransform 是动画变换基类。内置动画均继承自它,并支持链式设置缓动与完成回调。
完成回调
QPosTransform((0, 0), (100, 100), 0.8).setFinishAnimBackCall(
lambda: print("动画完成")
)缓动模式
from .QuModLibs.Modules.UI.Anims import QPosTransform, QTransform
QPosTransform((0, 0), (100, 100), 0.8).setEasingMode(
QTransform.EasingMode.EaseOutQuad
)
# 也可以修改全局默认缓动类型。
QTransform.EasingMode.Default = QTransform.EasingMode.EaseOutQuad当前内置缓动:
QTransform.EasingMode.Linear:线性。QTransform.EasingMode.EaseInSide:渐入。QTransform.EasingMode.EaseOutQuad:渐出。
内置动画类型
from .QuModLibs.Modules.UI.Anims import QPosTransform, QSizeTransform, QAlphaTransform, QuTypeWriter
QPosTransform((0, 0), (100, 100), 0.8)
QSizeTransform((10, 10), (100, 100), 0.8, resizeChildren=False)
QAlphaTransform(0.0, 1.0, 0.8)
QuTypeWriter("你好, 世界", 1.2, childPath="", syncSize=False)QPosTransform:坐标动画。QSizeTransform:大小动画,可选择是否重算子节点。QAlphaTransform:透明度动画,仅支持图片/文字控件。QuTypeWriter:打字机动画,仅支持文字控件。
旧式手动管理 已过时
早期写法直接创建 QAnimsControl,并在 Tick / 帧事件中手动调用 update()。该方式需要自行管理监听和释放,新项目不推荐使用。
# -*- coding: utf-8 -*-
from .QuModLibs.Client import *
from .QuModLibs.UI import EasyScreenNodeCls
from .QuModLibs.Modules.UI.Anims import QAnimsControl, QPosTransform
@EasyScreenNodeCls.Binding("test_ui.main")
class TestUI(EasyScreenNodeCls):
def __init__(self):
self.imgPath = "/panel/image"
self.imgAnimObj = QAnimsControl.bindControl(self, self.imgPath)
@EasyScreenNodeCls.Listen("OnScriptTickClient")
def onTick(self, _={}):
self.imgAnimObj.update()
@EasyScreenNodeCls.OnClick("/panel/move")
def onMove(self):
self.imgAnimObj.changeTransformAnim(
QPosTransform(self.imgAnimObj.getPos(), (400, 100), useTime=0.8)
)旧式 bindNode 已过时
QAnimManager.bindNode(uiNode) 通过旧式 Auto Tick 生命周期管理动画,主要用于非 QuModLibs UI 或历史项目维护。新项目请使用 bindRAIINode。
from .QuModLibs.UI import EasyScreenNodeCls
from .QuModLibs.Modules.UI.Anims import QAnimManager
@EasyScreenNodeCls.Binding("test_ui.main")
class TestUI(EasyScreenNodeCls):
def __init__(self):
self.animSystem = QAnimManager.bindNode(self)