PyQt5,屬性與屬性動畫

0.前言

Qt框架提供了一個基於其元對象系統的屬性系統,應用也比較廣泛,如屬性動畫、樣式表屬性、QML屬性等。Python3也有一個property屬性,但和Qt屬性不是通用的。

我們可以動態設置和獲取QObject及子類對象的屬性:

    w.setProperty('size',QSize(600,600))
    print(w.property('size'))

除了Qt預定義的一些屬性,也可以添加自定義的屬性。使用setProperty動態添加,或者用pyqtProperty提前定義好屬性。 

1.使用pyqtProperty裝飾器添加屬性

裝飾器的方式和Python3的屬性裝飾器寫法類似:

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
#from PyQt5.QtCore import QObject,pyqtProperty

#使用一個背景顏色動畫來展示Qt屬性
class MyLabel(QLabel):
    def __init__(self):
        super().__init__()
        self.color=QColor(0,0,0)

        self.animation=QPropertyAnimation(self)
        self.animation.setTargetObject(self) #綁定目標對象
        self.animation.setPropertyName(b'mycolor') #bytearray類型
        self.animation.setStartValue(QColor(255,0,0))
        self.animation.setEndValue(QColor(0,255,255))
        self.animation.setDuration(2000) #2s=2000ms     
        self.animation.setLoopCount(-1) #一直循環
        self.animation.start() #啓動動畫


    def paintEvent(self,event):
        super().paintEvent(event)
        painter=QPainter(self)
        painter.fillRect(self.rect(),self.color)

    #獲取屬性值
    @pyqtProperty(QColor)
    def mycolor(self):
        return self.color

    #設置屬性值,也可以寫@mycolor.write
    @mycolor.setter
    def mycolor(self,value):
        self.color=value
        self.update()


if __name__ == "__main__":
    app=QApplication(sys.argv)

    w=MyLabel()
    w.setWindowTitle("龔建波 1992")
    w.resize(400,400)
    w.show()
   
    sys.exit(app.exec_())

2.使用pyqtProperty函數添加屬性

可以使用pyqtProperty函數定義新的Qt屬性,它的使用方式也和Python3的property函數相同,以這種方式定義的Qt屬性也可以充當Python屬性。函數原型有點長:

PyQt5.QtCore.pyqtProperty(type[, fget=None[, fset=None[, freset=None[, fdel=None[, doc=None[, designable=True[, scriptable=True[, stored=True[, user=False[, constant=False[, final=False[, notify=None[, revision=0]]]]]]]]]]]]])

參數說明(除了類型,都是可選的):

  • type –屬性的類型。它可以是Python類型的對象,也可以是C ++類型名稱的字符串。

  • fget –用於獲取屬性值的可調用對象。

  • fset –用於設置屬性值的可調用對象。

  • freset –用於將屬性的值重置爲其默認值的可調用對象。

  • fdel –用於刪除屬性可調用對象。

  • doc –屬性的文檔描述。

  • designable –設置Qt DESIGNABLE標誌,。

  • scriptable –設置Qt SCRIPTABLE標誌。

  • stored –設置Qt STORED標誌。

  • user –設置Qt USER標誌。

  • constant –設置Qt CONSTANT標誌。

  • final –設置Qt FINAL標誌。

  • notify –變量修改通知信號。

  • version –版本導出到QML。

返回類型:

  • 屬性對象。

相關說明見:https://blog.csdn.net/gongjianbo1992/article/details/105243829

比較常用的幾個設置是:type類型、fget獲取值、fset設置值、notify值改變信號。

修改一下上面那個例子:

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
#from PyQt5.QtCore import QObject,pyqtProperty

#使用一個背景顏色動畫來展示Qt屬性
class MyLabel(QLabel):
    def __init__(self):
        super().__init__()
        self.color=QColor(0,0,0)
        #... ...

    #函數名是任意的,只是作爲回調
    def get_mycolor(self):
        return self.color

    def set_mycolor(self,value):
        self.color=value
        self.update()

    #添加屬性,注意放的位置
    mycolor=pyqtProperty(QColor,fget=get_mycolor,fset=set_mycolor)

3.動畫組

有了屬性的基礎後,就可以開始寫我們的動畫組了,也就是多個屬性動畫串行或並行執行。

QAnimationGroup動畫組有兩個子類,QSequentialAnimationGroup串行動畫和QParallelAnimationGroup並行動畫,並且動畫組之間也可以嵌套。此外,動畫還可以暫停(pause)和反序(設置direction)執行。

下面用一個簡單的動畫組來演示:

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
#from PyQt5.QtCore import QObject,pyqtProperty

#使用一個背景顏色動畫來展示Qt屬性
class MyLabel(QLabel):
    def __init__(self):
        super().__init__()
        self.color=QColor(255,255,255)

        #顏色動畫-開始
        self.anim_color=QPropertyAnimation(self)
        self.anim_color.setTargetObject(self)
        self.anim_color.setPropertyName(b'mycolor') #bytearray類型
        self.anim_color.setStartValue(QColor(255,255,255))
        self.anim_color.setEndValue(QColor(0,255,0))
        self.anim_color.setDuration(2000) #2s=2000ms  
        #尺寸+位置動畫-開始  geometry爲QWidget屬性
        self.anim_rect=QPropertyAnimation(self,b'geometry',parent=self)
        #根據屏幕大小計算中間位置
        the_screen_center=self.screen().geometry().center()
        the_min_rect=QRect(0,0,200,200)
        the_min_rect.moveCenter(the_screen_center)
        the_max_rect=QRect(0,0,400,400)
        the_max_rect.moveCenter(the_screen_center)
        self.anim_rect.setStartValue(the_min_rect)
        self.anim_rect.setEndValue(the_max_rect)
        self.anim_rect.setDuration(2000) #2s=2000ms  

        #並行動畫組
        self.anim_parallel=QParallelAnimationGroup(self)
        self.anim_parallel.addAnimation(self.anim_color)
        self.anim_parallel.addAnimation(self.anim_rect)

        #顏色動畫-恢復
        self.anim_color2=QPropertyAnimation(self)
        self.anim_color2.setTargetObject(self)
        self.anim_color2.setPropertyName(b'mycolor') #bytearray類型
        self.anim_color2.setStartValue(QColor(0,255,0))
        self.anim_color2.setEndValue(QColor(255,255,255))
        self.anim_color2.setDuration(2000) #2s=2000ms  
        #尺寸+位置動畫-恢復  
        self.anim_rect2=QPropertyAnimation(self,b'geometry',parent=self)
        self.anim_rect2.setStartValue(the_max_rect)
        self.anim_rect2.setEndValue(the_min_rect)
        self.anim_rect2.setDuration(2000) #2s=2000ms  

        #並行動畫組
        self.anim_sequential=QSequentialAnimationGroup(self)
        self.anim_sequential.addAnimation(self.anim_rect2)
        self.anim_sequential.addAnimation(self.anim_color2)

        #串聯兩個動畫組-循環播放
        self.anim_group=QSequentialAnimationGroup(self)
        self.anim_group.addAnimation(self.anim_parallel)
        self.anim_group.addAnimation(self.anim_sequential)
        self.anim_group.setLoopCount(-1) #循環播放
        self.anim_group.start()

    def paintEvent(self,event):
        super().paintEvent(event)
        painter=QPainter(self)
        painter.fillRect(self.rect(),self.color)

    #函數名是任意的,只是作爲回調
    def get_mycolor(self):
        return self.color

    def set_mycolor(self,value):
        self.color=value
        self.update()

    #添加屬性,注意放的位置
    mycolor=pyqtProperty(QColor,fget=get_mycolor,fset=set_mycolor)

if __name__ == "__main__":
    app=QApplication(sys.argv)

    w=MyLabel()
    w.setWindowTitle("龔建波 1992")
    w.show()
   
    sys.exit(app.exec_())

4.參考

文檔:https://www.riverbankcomputing.com/static/Docs/PyQt5/qt_properties.html

博客:https://www.cnblogs.com/liming19680104/p/10425347.html

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