同以往一樣,我們先來看看程序的結構,整個程序大約205行,一共涉及6個類,如下圖:
這個類繼承了QPropertyAnimation,我們在
學點編程吧:PyQt5番外篇(3):2018情人節特刊?zhuanlan.zhihu.com
中曾經介紹過。
我們這裡用到了QPropertyAnimation這個類。QPropertyAnimation類定義了Qt的屬性動畫。
QPropertyAnimation以Qt屬性做差值,作為屬性值存儲在QVariants中,該類繼承自QVariantAnimation,並支持基類相同的元類型動畫。
animation = QPropertyAnimation(myWidget, b"geometry") animation.setDuration(10000) animation.setStartValue(QRect(0, 0, 100, 30)) animation.setEndValue(QRect(250, 250, 100, 30))
animation.start()
聲明屬性的類必須是一個QObject,為了能夠讓屬性可以用做動畫效果,必須提供一個setter(這裡是:b」geometry」),這樣QPropertyAnimation纔可以設置屬性的值。注意:這能夠使它讓許多Qt控制項產生動畫效果。
首先,我們通過構造函數創建一個QPropertyAnimation對象,其中myWidget表示動畫作用的QObject對象,geometry則表示QObject的屬性。然後,可以指定屬性的開始值和結束值。
QVariantAnimation類詳細的描述瞭如何設置動畫。需要注意的是:如果沒有設置起始值,在QPropertyAnimation實例被創建時,屬性就會設置起始值為它有的值。
QPropertyAnimation就其本身而言非常奏效。對於複雜的動畫,例如:包含多個對象,則可以使用QAnimationGroup,動畫組是一個可以包含其它動畫的動畫,並可以管理動畫的播放。
class Animation(QPropertyAnimation):
def __init__(self, target, prop): super(Animation, self).__init__(target, prop)
def updateCurrentTime(self, currentTime): self.m_path = QPainterPath() if self.m_path.isEmpty(): end = self.endValue() start = self.startValue() self.m_path.addEllipse(QRectF(start, end))
dura = self.duration()
if dura == 0: progress = 1.0 else: progress = (((currentTime - 1) % dura) + 1) / float(dura)
easedProgress = self.easingCurve().valueForProgress(progress)
if easedProgress > 1.0: easedProgress -= 1.0 elif easedProgress < 0: easedProgress += 1.0
pt = self.m_path.pointAtPercent(easedProgress) self.updateCurrentValue(pt)
def startAnimation(self, startx, starty, endx, endy, duration): self.setStartValue(QPointF(startx, starty)) self.setEndValue(QPointF(endx, endy)) self.setDuration(duration) self.setLoopCount(-1) self.start()
當動畫發生的時候,currentTime(此屬性保存動畫的當前時間和進度)總是在變化的。每次動畫的currentTime更改時,都會調用updateCurrentTime()函數。所以我們重寫該函數,好讓動畫的運行軌道能夠符合我們的要求。
target, prop這個兩個參數分別對應:動畫的產生對象和setter。
self.m_path = QPainterPath() if self.m_path.isEmpty(): end = self.endValue() start = self.startValue() self.m_path.addEllipse(QRectF(start, end))
首先判斷下我們的路徑中是否增加了元素,很明顯一開始沒有,所以我們才會執行下面的語句。
設定行星的運行軌道,這裡是一個橢圓形。
endValue()、startValue()分別表示動畫的結束值和起始值。
self.m_path.addEllipse(QRectF(start, end))
在指定的boundingRectangle內創建一個橢圓,這裡是QRectF(start, end),並將其作為封閉的子路徑添加到painter路徑中。
dura = self.duration() progress = (((currentTime - 1) % dura) + 1) / float(dura)
duration()此屬性保存動畫的持續時間(以毫秒為單位)。 默認持續時間為250毫秒。progress則描繪了當前的完成比率。
easedProgress = self.easingCurve().valueForProgress(progress) if easedProgress > 1.0: easedProgress -= 1.0 elif easedProgress < 0: easedProgress += 1.0
返回進度緩和曲線的有效進度。 進度必須介於0和1之間,而返回的有效進度可能超出這些範圍。大於1就減1,小於0就加1。
pt = self.m_path.pointAtPercent(easedProgress)
返回當前路徑的百分比easedProgress處的點。 參數easedProgress必須介於0和1之間。當存在曲線時,百分比參數被映射到貝塞爾方程的t參數。
self.updateCurrentValue(pt)
每次動畫的當前值更改時,都會調用updateCurrentValue()。pt參數是新的當前值。沒有這個函數動畫動不了。
setStartValue()、setEndValue()分別表示設置動畫的起止位置,setDuration()設置動畫的運行時間,
self.setLoopCount(-1)
此屬性保存動畫的循環計數,動畫的循環計數描述為整數。 默認情況下,此值為1,表示動畫應僅運行一次,然後停止。 通過更改它,您可以讓動畫循環多次。 如果值為0,則動畫將根本不運行,並且值為-1時,動畫將永遠循環直至停止。 不支持在具有未定義持續時間的動畫上進行循環。 它只會運行一次。
start()表示開始運行動畫。
我們下期再見!
如果你喜歡本篇文章,請給我點贊
讚賞(推薦)
分享給你的好友們吧!
歡迎關注微信公眾號:學點編程吧。加油!
(? ??_??)? (*????)