PySide6的QTimeLine详解

QTimeLine是PySide6 中用于实现时间线动画的核心类,它的本质是在一段指定时间内,从一个起始值平滑过渡到一个结束值。

一、基础用法:

python 复制代码
timeLine = QTimeLine(500, None)  # 定义一个500毫秒的时间线
timeLine.valueChanged.connect(on_time_line)  # 连接valueChanged信号
timeLine.start()  # 开始时间线

二、完整实例:

python 复制代码
import sys

from PySide6.QtCore import QTimeLine, QElapsedTimer, Slot
from PySide6.QtWidgets import QApplication

app = QApplication(sys.argv)
i = 0
# 创建一个计时器统计时间线的耗时
timer = QElapsedTimer()
timer.start()

# 定义一个槽函数,用于处理时间线
@Slot(float)
def on_time_line(value):
    global i
    if value < 1:
        i += 1
        print(f"序号:{i},  输出值:{value},  耗时(毫秒): {timer.elapsed()}")
        return
    app.quit()

timeLine = QTimeLine(500, None)  # 定义一个500毫秒的时间线
timeLine.valueChanged.connect(on_time_line)  # 连接valueChanged信号
timeLine.start()  # 开始时间线

app.exec()

运行结果:

python 复制代码
序号:1,  输出值:0.014184133542663013,  耗时(毫秒): 38
序号:2,  输出值:0.06962898649802818,  耗时(毫秒): 85
序号:3,  输出值:0.15317334709359753,  耗时(毫秒): 128
序号:4,  输出值:0.27862088448054917,  耗时(毫秒): 177
序号:5,  输出值:0.4093971181864313,  耗时(毫秒): 221
序号:6,  输出值:0.5564281924367408,  耗时(毫秒): 268
序号:7,  输出值:0.7014532178568313,  耗时(毫秒): 316
序号:8,  输出值:0.8330059337171258,  耗时(毫秒): 366
序号:9,  输出值:0.928763328096826,  耗时(毫秒): 414
序号:10,  输出值:0.9835007438812176,  耗时(毫秒): 459

时间线启动后,它每隔若干毫秒(或每一帧)发射一个实数信号并被槽函数接收,信号的值从0.0到1.0线性增长,这就是QTimeLine基本工作过程。

三、最常用函数和方法

**1、setLoopCount():**设置循环次数。

2、**setFrameRange(start, end):**设置帧的范围(起始帧、结束帧)。当设置了帧的范围,就用frameChanged信号传递帧信息而不是之前的valueChanged:

python 复制代码
import sys

from PySide6.QtCore import QTimeLine, QElapsedTimer, Slot, QObject
from PySide6.QtWidgets import QApplication


class TimeLineDemo(QObject):
    def __init__(self):
        super().__init__()
        self.timeLine = QTimeLine(2000, self)  # 定义一个2000毫秒的时间线
        self.timeLine.setFrameRange(5, 11)  # 设置时间线帧号的范围为5到11(时间仍然是0--2000毫秒)
        self.timeLine.frameChanged.connect(self.on_time_line)  # 连接frameChanged信号
        self.timeLine.finished.connect(app.quit)  # 当时间线结束时退出应用
        self.timeLine.start()  # 开始时间线

    def on_time_line(self, frame):
        print(f"frame:{frame},{self.timeLine.currentFrame()} , 时间点:{self.timeLine.currentTime()}, value:{self.timeLine.currentValue()}")

app = QApplication(sys.argv)

demo = TimeLineDemo()

app.exec()

运行结果:

python 复制代码
frame:6,6 , 时间点:557, value:0.17947607153759376
frame:7,7 , 时间点:788, value:0.33655598517252877
frame:8,8 , 时间点:1021, value:0.516490370457325
frame:9,9 , 时间点:1253, value:0.6935164234684597
frame:10,10 , 时间点:1493, value:0.8496445738009342
frame:11,11 , 时间点:2000, value:1.0

**3、setDirection():**运行方向。默认正增长,value和时间都是从0开始递增。当设置了反向后,value和时间都是从最大值开始递减:

python 复制代码
import sys

from PySide6.QtCore import QTimeLine, QElapsedTimer, Slot, QObject
from PySide6.QtWidgets import QApplication


class TimeLineDemo(QObject):
    def __init__(self):
        super().__init__()
        self.timeLine = QTimeLine(500, self)  # 定义一个时间线
        self.timeLine.setDirection(QTimeLine.Backward)  # 设置为反向
        self.timeLine.valueChanged.connect(self.on_time_line)  # 连接信号
        self.timeLine.finished.connect(app.quit)  # 当时间线结束时退出应用
        self.timeLine.start()  # 开始时间线

    def on_time_line(self, value):
        print(f"时间点:{self.timeLine.currentTime()}, value:{self.timeLine.currentValue()}")

app = QApplication(sys.argv)

demo = TimeLineDemo()

app.exec()
python 复制代码
C:\Users\DY\.conda\envs\pyside\python.exe E:\HiKi_MVS\tmp\tmp2.py 
时间点:500, value:1.0
时间点:455, value:0.9801468428384715
时间点:408, value:0.9187640200210708
时间点:356, value:0.8089298065451671
时间点:312, value:0.6898895477609005
时间点:265, value:0.5470541566592572
时间点:220, value:0.40630934270713764
时间点:170, value:0.2591231629491424
时间点:123, value:0.1420317584890844
时间点:74, value:0.05307928792436811
时间点:33, value:0.010709547837263966
时间点:0, value:-0.0

进程已结束,退出代码为 0

**4、setDuration():**设置持续时间

python 复制代码
self.timeLine = QTimeLine(parent=self)  # 定义一个时间线,初始化时并不定义持续时间
self.timeLine.setDuration(2000)  # 设置时间线持续时间为2秒

四、函数和方法总结

1、核心配置函数(动画基础设置)

这类函数用于定义动画的核心参数,是使用 QTimeLine 的基础。

函数 功能说明 示例
setDuration(ms) 设置动画总时长(单位:毫秒),决定动画执行的快慢 timeline.setDuration(3000) # 动画持续 3 秒
setFrameRange(start, end) 设置帧的范围(起始帧、结束帧),决定 currentFrame() 的取值范围 timeline.setFrameRange(0, 200) # 帧从 0 到 200
setStartFrame(frame) / setEndFrame(frame) 单独设置起始帧 / 结束帧(替代 setFrameRange 的拆分写法) timeline.setStartFrame(10)``timeline.setEndFrame(100)
2、状态控制函数(动画的启停 / 重置)

这类函数用于控制动画的执行状态,是动态操作动画的关键。

函数 功能说明 注意点
start() 启动 / 重启时间线动画 若动画已在运行,调用后会从头重新开始
stop() 停止当前动画,保留当前进度(再次 start() 会从停止位置继续) 区别于 reset()
setPaused() 暂停动画,保留当前进度
resume() 恢复暂停的动画 需和 pause() 配合使用
toggleDirection``() 切换方向
3、进度 / 数值获取函数(实时获取动画状态)

这类函数用于获取动画的实时进度或数值,常配合信号使用。

函数 功能说明 对比 / 补充
currentValue() 返回 0.0~1.0 的归一化进度(浮点数) 核心:currentFrame() 是整数帧值,currentValue() 是比例值示例:动画执行到一半时返回 0.5
currentTime() 返回动画已执行的时间(单位:毫秒) 范围:0 ~ 总时长(duration())示例:总时长 3000ms,执行 1 秒后返回 1000
duration() 获取动画总时长(返回设置的毫秒数) 对应 setDuration(),只读
startFrame() / endFrame() 获取设置的起始帧 / 结束帧 对应 setStartFrame()/setEndFrame(),只读
state() 返回当前时间线的状态(枚举值) 状态枚举:- QTimeLine.State.NotRunning:未运行- QTimeLine.State.Running:运行中- QTimeLine.State.Paused:暂停中
4、行为设置函数(控制动画的循环 / 曲线)

这类函数用于定制动画的执行方式,让动画更符合业务需求。

函数 功能说明 常用参数 / 示例
setLoopCount(count) 设置动画循环次数 - 0:无限循环- 1:默认(只执行 1 次)- 3:循环 3 次示例:timeline.setLoopCount(0) # 无限循环
setEasingCurv() 设置动画的缓动曲线(控制速度变化) 曲线的详细介绍见下表
setDirection(direction) 设置动画的播放方向 方向枚举:- QTimeLine.Direction.Forward:正向(从 startFrame 到 endFrame)- QTimeLine.Direction.Backward:反向(从 endFrame 到 startFrame)示例:timeline.setDirection(QTimeLine.Backward)
5、动画的缓动曲线详解:

Qt 的 QEasingCurve 提供了几十种缓动曲线,其所有枚举值在QtCore.py下:

python 复制代码
class QEasingCurve(Shiboken.Object):

    class Type(enum.Enum):

        Linear                   : QEasingCurve.Type = ... # 0x0
        InQuad                   : QEasingCurve.Type = ... # 0x1
        OutQuad                  : QEasingCurve.Type = ... # 0x2
        InOutQuad                : QEasingCurve.Type = ... # 0x3
        OutInQuad                : QEasingCurve.Type = ... # 0x4
        InCubic                  : QEasingCurve.Type = ... # 0x5
        OutCubic                 : QEasingCurve.Type = ... # 0x6
        InOutCubic               : QEasingCurve.Type = ... # 0x7
        OutInCubic               : QEasingCurve.Type = ... # 0x8
        InQuart                  : QEasingCurve.Type = ... # 0x9
        OutQuart                 : QEasingCurve.Type = ... # 0xa
        InOutQuart               : QEasingCurve.Type = ... # 0xb
        OutInQuart               : QEasingCurve.Type = ... # 0xc
        InQuint                  : QEasingCurve.Type = ... # 0xd
        OutQuint                 : QEasingCurve.Type = ... # 0xe
        InOutQuint               : QEasingCurve.Type = ... # 0xf
        OutInQuint               : QEasingCurve.Type = ... # 0x10
        InSine                   : QEasingCurve.Type = ... # 0x11
        OutSine                  : QEasingCurve.Type = ... # 0x12
        InOutSine                : QEasingCurve.Type = ... # 0x13
        OutInSine                : QEasingCurve.Type = ... # 0x14
        InExpo                   : QEasingCurve.Type = ... # 0x15
        OutExpo                  : QEasingCurve.Type = ... # 0x16
        InOutExpo                : QEasingCurve.Type = ... # 0x17
        OutInExpo                : QEasingCurve.Type = ... # 0x18
        InCirc                   : QEasingCurve.Type = ... # 0x19
        OutCirc                  : QEasingCurve.Type = ... # 0x1a
        InOutCirc                : QEasingCurve.Type = ... # 0x1b
        OutInCirc                : QEasingCurve.Type = ... # 0x1c
        InElastic                : QEasingCurve.Type = ... # 0x1d
        OutElastic               : QEasingCurve.Type = ... # 0x1e
        InOutElastic             : QEasingCurve.Type = ... # 0x1f
        OutInElastic             : QEasingCurve.Type = ... # 0x20
        InBack                   : QEasingCurve.Type = ... # 0x21
        OutBack                  : QEasingCurve.Type = ... # 0x22
        InOutBack                : QEasingCurve.Type = ... # 0x23
        OutInBack                : QEasingCurve.Type = ... # 0x24
        InBounce                 : QEasingCurve.Type = ... # 0x25
        OutBounce                : QEasingCurve.Type = ... # 0x26
        InOutBounce              : QEasingCurve.Type = ... # 0x27
        OutInBounce              : QEasingCurve.Type = ... # 0x28
        InCurve                  : QEasingCurve.Type = ... # 0x29
        OutCurve                 : QEasingCurve.Type = ... # 0x2a
        SineCurve                : QEasingCurve.Type = ... # 0x2b
        CosineCurve              : QEasingCurve.Type = ... # 0x2c
        BezierSpline             : QEasingCurve.Type = ... # 0x2d
        TCBSpline                : QEasingCurve.Type = ... # 0x2e
        Custom                   : QEasingCurve.Type = ... # 0x2f
        NCurveTypes              : QEasingCurve.Type = ... # 0x30

设置方法如下:

python 复制代码
# 简略写法
self.timeLine.setEasingCurve(QEasingCurve.Linear)
# 或:
self.timeLine.setEasingCurve(QEasingCurve.Type.InQuart)

1). 基础线性(无缓动)

曲线类型 效果说明 适用场景
Linear 匀速运动,无加速 / 减速,最生硬 进度条匀速填充、纯机械感的动画

2). 二次曲线(Quad):平滑基础款

基于二次函数(平方)的缓动,是最常用的基础平滑曲线,分为 3 种节奏:

曲线类型 效果说明
InQuad 动画开始慢,逐渐加速(只加速)
OutQuad 动画开始快,逐渐减速(只减速)
InOutQuad 先加速、中间最快、后减速

3). 高次曲线(Cubic/Quartic/Quint):更夸张的加速 / 减速

比二次曲线的加速 / 减速效果更明显,数值越大(Quint > Quartic > Cubic),节奏反差越强:

曲线类型 效果说明
InCubic/OutCubic/InOutCubic 三次方曲线,加速 / 减速比 Quad 更陡
InQuart/OutQuart/InOutQuart 四次方曲线,反差更强
InQuint/OutQuint/InOutQuint 五次方曲线,最夸张的平滑加速 / 减速

4). 指数 / 正弦曲线:非线性平滑

曲线类型 效果说明
InExpo/OutExpo/InOutExpo 指数级加速 / 减速(开始极慢 / 结束极慢)
InSine/OutSine/InOutSine 正弦曲线,比 Quad 更柔和的缓动(接近物理 "轻推" 效果)

5). 弹性 / 弹跳曲线:带回弹效果

模拟弹簧、弹跳的物理效果,适合活泼的动效:

曲线类型 效果说明
InElastic 动画开始前先反向回弹一下,再加速前进
OutElastic 动画到终点后,超出一点再回弹到目标位置**(最常用)**
InOutElastic 开始和结束都有回弹
OutBounce 动画到终点前多次小弹跳(像皮球落地)
InBounce 动画开始前多次小弹跳
InOutBounce 开始和结束都有弹跳

6). 阶跃 / 圆形曲线:特殊效果

曲线类型 效果说明
InCirc/OutCirc/InOutCirc 圆形曲线,比指数曲线更极端的缓动
InBack/OutBack/InOutBack 回退曲线:OutBack 会先超过目标位置再拉回(类似 "拉橡皮筋")
InCurve/OutCurve Qt 早期兼容的曲线,效果接近 InSine/OutSine
SineCurve 等价于 InOutSine
6、实用示例

下面是一个综合示例:

python 复制代码
import sys

from PySide6.QtCore import QTimeLine, QElapsedTimer, Slot, QObject, QEasingCurve
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton


class TimeLineDemo(QWidget):
    def __init__(self):
        super().__init__()
        self.timeLine = QTimeLine(parent=self)  # 定义一个时间线
        self.timeLine.setDuration(10000)  # 设置时间线持续时间为10秒
        self.timeLine.valueChanged.connect(self.on_time_line)  # 连接信号
        layout = QVBoxLayout(self)
        self.label = QLabel("时间线示例", self)
        layout.addWidget(self.label)
        self.btn1 = QPushButton("启动时间线")
        layout.addWidget(self.btn1)
        self.btn1.clicked.connect(self.timeLine.start)
        self.btn2 = QPushButton("暂停时间线")
        layout.addWidget(self.btn2)
        self.btn2.clicked.connect(lambda :self.timeLine.setPaused(True))
        self.btn3 = QPushButton("继续时间线")
        layout.addWidget(self.btn3)
        self.btn3.clicked.connect(lambda :self.timeLine.setPaused(False))
        self.btn4 = QPushButton("停止时间线")
        layout.addWidget(self.btn4)
        self.btn4.clicked.connect(self.timeLine.stop)
        self.btn5 = QPushButton("切换方向")
        layout.addWidget(self.btn5)
        self.btn5.clicked.connect(self.timeLine.toggleDirection)

    def on_time_line(self, value):
        t = f"时间点:{self.timeLine.currentTime()}, value:{self.timeLine.currentValue()}"
        self.label.setText(t)


app = QApplication(sys.argv)
window = TimeLineDemo()
window.show()

app.exec()

五、信号

QTimeLine的信号是驱动动画交互的核心,每个信号对应动画执行的不同阶段,以下是QTimeLine的信号列表:

信号名 触发时机 参数说明 典型使用场景
frameChanged(int frame) 动画推进过程中,每一帧数值发生变化时触发 frame:当前最新的帧值(和 currentFrame() 一致) 更新 UI 显示(如数字变化、控件位置)、实时同步动画状态
valueChanged(float value) 动画推进过程中,归一化进度值变化时触发 value:0.0~1.0 的浮点数(和 currentValue() 一致) 基于比例的动画(如控件宽度 / 高度变化、透明度调整)
stateChanged(QTimeLine.State newState) 时间线的运行状态发生改变时触发 newState:新状态(枚举值:NotRunning/Running/Paused 监听动画启停 / 暂停状态,更新按钮文字(如「暂停」→「恢复」)
finished() 动画正常执行完毕时触发(单次动画结束 / 循环次数用尽) 无参数 动画结束后执行收尾操作(如隐藏控件、触发下一个动画)

信号使用关键注意事项:

  1. frameChanged vs valueChanged
    • 两者触发时机几乎同步,但参数类型不同:frameChanged 传整数帧值,valueChanged 传 0.0~1.0 浮点数;
    • 优先用 frameChanged 处理「整数计数」场景(如页码、步数),用 valueChanged 处理「比例计算」场景(如控件尺寸、透明度)。
  2. finished 信号的触发条件
    • 只有动画「正常执行完所有循环次数」才会触发;
    • 若手动调用 stop()终止动画,不会触发 finished
  3. stateChanged 监听状态
    • 可通过该信号实现「按钮文字随状态变化」(如运行中按钮显示「暂停」,暂停时显示「恢复」)。
总结
  1. frameChanged/valueChanged 是动画过程中最常用的信号,分别返回整数帧值和浮点比例值;
  2. stateChanged 监听动画启停 / 暂停状态,finished 监听动画正常结束,是控制动画生命周期的核心;
  3. directionChanged 监听播放方向变化,适合需要反向播放的动画场景。

这些信号覆盖了 QTimeLine 动画交互的全场景,组合使用就能实现灵活的动画控制逻辑。

总结

  1. 核心配置setDuration()(时长)、setFrameRange()(帧范围)是动画的基础,必须优先设置;
  2. 状态控制start()/stop()/pause/resume 控制动画启停;
  3. 数值获取currentValue()(比例)、currentTime()(已执行时间)、state()(状态)是实时监控动画的核心;
  4. 行为定制setLoopCount()(循环)、setCurveShape()(速度曲线)、setDirection()(播放方向)让动画更灵活。

这些函数基本覆盖了 QTimeLine 日常使用的 大部分场景,掌握后就能实现大部分基础的时间线动画效果(如控件移动、数值变化、颜色过渡等)。

相关推荐
纯.Pure_Jin(g)2 小时前
【Python练习四】Python 算法与进阶特性实战:数组、序列化与位运算专项练习(3道经典练习带你巩固基础——看完包会)
开发语言·vscode·python
GHL2842710902 小时前
TensorFlow学习
人工智能·学习
星火开发设计2 小时前
虚析构函数:解决子类对象的内存泄漏
java·开发语言·前端·c++·学习·算法·知识
2501_901147832 小时前
幂函数实现的优化与工程思考笔记
笔记·算法·面试·职场和发展·php
龙山云仓2 小时前
No152:AI中国故事-对话祖冲之——圆周率与AI精度:数学直觉与极限探索
大数据·开发语言·人工智能·python·机器学习
琅琊榜首20202 小时前
AI+Python实操指南:用编程赋能高质量网络小说创作
开发语言·人工智能·python
Faker66363aaa2 小时前
基于YOLO13-C3k2-Strip的神经退行性疾病MRI影像自动识别
python
Dxy12393102162 小时前
Python 将 JSON 字符串转换为字典
前端·python·json
爱搞事的程小猿2 小时前
qml自定义扩展模块
c++·qt·qml