一个动画由多张静态图片组成,每一张静态图片为一帧。每隔一定时间显示一帧,如果时间间隔非常短的话,那这些静态图片就会构成一个连续影像,动画由此而来。QTimeLine提供了用于控制动画的时间轴,它在实现动画效果方面非常快速有用
1 import sys 2 from PyQt5.QtCore import QTimeLine 3 from PyQt5.QtWidgets import QApplication, QWidget, QLabel 4 5 6 class Demo(QWidget): 7 def __init__(self): 8 super(Demo, self).__init__() 9 self.resize(600, 600) 10 11 self.label = QLabel('Hello PyQt5', self) 12 self.label.move(-100, 100) 13 14 self.timeline = QTimeLine(5000, self) # 实例化一个时间轴,持续时间为5秒 15 self.timeline.setFrameRange(0, 700) #设置帧率范围,该值表示在规定的时间内将要执行多少帧 16 self.timeline.frameChanged.connect(self.set_frame_func) #帧数变化时发出信号 17 #当动画开始后,帧数就会发生改变,每次帧数发生变化,就会发出frameChanged信号(该信号发送时附带当前所在帧数) 18 self.timeline.setLoopCount(0) # 传入0代表无限循环运行.传入正整数会运行相应次数,传入负数不运行 19 self.timeline.start() #启动动画 20 21 def set_frame_func(self, frame):#参数:接受到的帧数 22 self.label.move(-100 + frame, 100) 23 24 25 if __name__ == '__main__': 26 app = QApplication(sys.argv) 27 demo = Demo() 28 demo.show() 29 sys.exit(app.exec_())
现在来重点说一下QTimeLine的状态,一共有以下三种:
- QTimeLine.NotRunning = 0
- QTimeLine.Running =2
- QTimeLine.Paused =1
在未开始或者运行结束时,QTimeLine就会处于NotRunning状态;当调用start()方法启动后,变为Running状态,期间QTimeLine会不断发出frameChanged信号;而当在运行中调用setPaused(True)让QTimeLine暂停的话,状态就会变为Paused。每当状态发生改变,QTimeLine都会发出stateChanged信号,我们可以根据该信号来判断动画所处的状态并作相应的处理
以下四个方法用于改变QTimeLine状态:
start():让QTimeLine进入Running状态。
stop():让QTimeLine进入NotRunning状态。
resume():让QTimeLine从Paused状态或者NotRunning状态转为Running状态,动画从当前帧继续(注意start()方法不是从当前帧继续,而是直接从头开始)。
setPaused():传入True,让QTimeLine进入Paused状态;传入False,让QTimeLine进入Running状态(传入False时QTimeLine的状态必须为Paused)。
1 import sys 2 from PyQt5.QtCore import QTimeLine 3 from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QHBoxLayout, QVBoxLayout 4 5 6 class Demo(QWidget): 7 def __init__(self): 8 super(Demo, self).__init__() 9 self.resize(600, 600) 10 11 self.label = QLabel('Hello PyQt5', self) 12 self.label.move(-100, 100) 13 14 self.timeline = QTimeLine(5000, self) 15 self.timeline.setFrameRange(0, 700) 16 self.timeline.frameChanged.connect(self.set_frame_func) 17 self.timeline.stateChanged.connect(lambda: print(self.timeline.state())) #状态变化时发出信号 18 #self.timeline.state() 返回当前的状态 19 self.timeline.setLoopCount(0) 20 21 self.start_btn = QPushButton('开始', self) 22 self.stop_btn = QPushButton('停', self) 23 self.pause_btn = QPushButton('暂停', self) 24 self.resume_btn = QPushButton('继续', self) 25 26 self.start_btn.clicked.connect(self.timeline.start) #单击开始按钮 27 self.stop_btn.clicked.connect(self.timeline.stop) #单击停按钮 28 self.pause_btn.clicked.connect(lambda: self.timeline.setPaused(True)) #单击暂停按钮 29 self.resume_btn.clicked.connect(self.timeline.resume) #单击继续按钮 30 31 self.h_layout = QHBoxLayout() 32 self.v_layout = QVBoxLayout() 33 self.h_layout.addWidget(self.start_btn) 34 self.h_layout.addWidget(self.stop_btn) 35 self.h_layout.addWidget(self.pause_btn) 36 self.h_layout.addWidget(self.resume_btn) 37 self.v_layout.addStretch(1) 38 self.v_layout.addLayout(self.h_layout) 39 self.setLayout(self.v_layout) 40 41 def set_frame_func(self, frame): 42 self.label.move(-100 + frame, 100) 43 44 45 if __name__ == '__main__': 46 app = QApplication(sys.argv) 47 demo = Demo() 48 demo.show() 49 sys.exit(app.exec_())
最后我们再来说一下QTimeLine的方向概念,一共有两种方向:
QTimeLine.Forward (默认方向)
QTimeLine.Backward
当为QTimeLine.Foward时,动画按照我们初始设定进行移动;而为QTimeLine.Backward时,我们可以实现一种动画反向的效果
1 import sys 2 from PyQt5.QtCore import QTimeLine 3 from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QHBoxLayout, QVBoxLayout 4 5 class Demo(QWidget): 6 def __init__(self): 7 super(Demo, self).__init__() 8 self.resize(600, 600) 9 10 self.label = QLabel('Hello PyQt5', self) 11 self.label.move(-100, 100) 12 13 self.timeline = QTimeLine(5000, self) 14 self.timeline.setFrameRange(0, 700) 15 self.timeline.frameChanged.connect(self.set_frame_func) 16 self.timeline.setLoopCount(0) 17 self.timeline.start() 18 19 self.forward_btn = QPushButton('正向', self) 20 self.backward_btn = QPushButton('反向', self) 21 self.forward_btn.move(150, 0) 22 self.backward_btn.move(350, 0) 23 self.forward_btn.clicked.connect(lambda: self.change_direction_func(self.forward_btn)) 24 self.backward_btn.clicked.connect(lambda: self.change_direction_func(self.backward_btn)) 25 26 def set_frame_func(self, frame): 27 self.label.move(-100 + frame, 100) 28 29 def change_direction_func(self, btn): 30 if btn == self.forward_btn: 31 self.timeline.setDirection(QTimeLine.Forward) #设置时间轴动画为正向 32 else: 33 self.timeline.setDirection(QTimeLine.Backward) #设置时间轴动画为反向 34 35 if __name__ == '__main__': 36 app = QApplication(sys.argv) 37 demo = Demo() 38 demo.show() 39 sys.exit(app.exec_())