PyQt動畫

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_()

運行效果:

如果你不是在簡書看到這篇文章,請移步簡書支持原作者

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章