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