1、创建一个动画
#-*- coding: utf-8 -*
__author__ = 'geebos'
from PyQt5.Qt import *
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
layout = QHBoxLayout()
self.setLayout(layout)
widget = QWidget()
widget.setStyleSheet('QWidget{background-color: red;}')
layout.addWidget(widget)
widget.setGeometry(QRect(0, 0, 100, 100))
# 绑定组件和属性
self.animation = QPropertyAnimation(widget, b'geometry')
# 设置动画时间
self.animation.setDuration(1000)
# 设置动画初始状态
self.animation.setStartValue(QRect(0, 0, 50, 50))
# 设置动画结束状态
self.animation.setEndValue(QRect(0, 0, 150, 150))
# 设置动画播放次数 -1表示无限
self.animation.setLoopCount(-1)
# 开始动画
self.animation.start()
self.setGeometry(300, 300, 380, 300)
self.setWindowTitle('Animation')
self.show()
if __name__ == "__main__":
app = QApplication([])
ex = Example()
ex.show()
app.exec_()
特别注意:
self.animation
不能改成 animation
,因为改成后者之后 animation
在初始化函数执行完后引用计数会变成 0,这时 python解释器会把 animation回收。最终导致本应该无限循环的动画在播放一段时间后不再播放,或者根本不播放。
运行效果:
2、动画序列
上一个例子只有放大部分的动画,我们还需要添加缩小部分的动画。这种需求可以通过 QSequentialAnimationGroup
来实现:
#-*- coding: utf-8 -*
__author__ = 'geebos'
from PyQt5.Qt import *
class Example(QWidget):
def __init__(self):
super(Example1, self).__init__()
layout = QHBoxLayout()
self.setLayout(layout)
widget = QWidget()
widget.setStyleSheet('QWidget{background-color: red;}')
layout.addWidget(widget)
widget.setGeometry(QRect(0, 0, 100, 100))
self.animation_group = QSequentialAnimationGroup()
# 绑定组件和属性
# 正向
animation = QPropertyAnimation(widget, b'geometry')
animation.setDuration(1000)
animation.setStartValue(QRect(0, 0, 50, 50))
animation.setEndValue(QRect(0, 0, 150, 150))
# 要添加到动画序列中的动画 不能单独调用 setLoopCount和 start
# animation.setLoopCount(-1)
# animation.start()
self.animation_group.addAnimation(animation)
# 反向
animation = QPropertyAnimation(widget, b'geometry')
animation.setDuration(1000)
animation.setStartValue(QRect(0, 0, 150, 150))
animation.setEndValue(QRect(0, 0, 50, 50))
self.animation_group.addAnimation(animation)
self.animation_group.setLoopCount(-1)
self.animation_group.start()
self.setGeometry(300, 300, 380, 300)
self.setWindowTitle('Animation')
self.show()
if __name__ == "__main__":
app = QApplication([])
ex = Example()
ex.show()
app.exec_()
运行效果:
3、操作其他属性
Qt自带的可操作的属性有限,只支持有 setter的属性。但是有时候有些属性没有 setter,比如 button的 size就没有对应的 setter函数,只能通过 setFixedSize函数来设置。这时我们可以重载 QPropertyAnimation
来实现我们的需求。
#-*- coding: utf-8 -*
__author__ = 'geebos'
from PyQt5.Qt import *
class PropertyAnimation(QPropertyAnimation):
def __init__(self, target, property):
super(PropertyAnimation, self).__init__(target, property.encode())
self._func = None
def setUpdateFunc(self, func):
# 设置动画触发时要执行的函数
self._func = func
def updateCurrentValue(self, value):
if self._func is None:
super(PropertyAnimation, self).updateCurrentValue(value)
else:
self._func(self.targetObject(), value)
class Example(QWidget):
def __init__(self):
super(Example2, self).__init__()
layout = QHBoxLayout()
self.setLayout(layout)
button = QPushButton('点我点我')
button.setFixedSize(QSize(100, 100))
button.setStyleSheet('QWidget{background-color: red;}')
layout.addWidget(button)
self.animation_group = QSequentialAnimationGroup()
def update(target, value):
# 更新函数,在这个函数里设置 button的大小
target.setFixedSize(value)
# 绑定组件和属性
# 正向
animation = PropertyAnimation(button, 'size')
animation.setUpdateFunc(update)
animation.setDuration(1000)
animation.setStartValue(QSize(50, 50))
animation.setEndValue(QSize(150, 150))
# 要添加到动画序列中的动画 不能单独调用 setLoopCount和 start
# animation.setLoopCount(-1)
# animation.start()
self.animation_group.addAnimation(animation)
# 反向
animation = PropertyAnimation(button, 'size')
animation.setUpdateFunc(update)
animation.setDuration(1000)
animation.setStartValue(QSize(150, 150))
animation.setEndValue(QSize(50, 50))
self.animation_group.addAnimation(animation)
self.animation_group.setLoopCount(-1)
self.animation_group.start()
self.setGeometry(300, 300, 380, 300)
self.setWindowTitle('Animation')
self.show()
if __name__ == "__main__":
app = QApplication([])
ex = Example()
ex.show()
app.exec_()
运行效果:
如果你不是在简书看到这篇文章,请移步简书支持原作者