Qt框架提供了一个基于其元对象系统的属性系统,应用也比较广泛,如属性动画、样式表属性、QML属性等。Python3也有一个property属性,但和Qt属性不是通用的。
我们可以动态设置和获取QObject及子类对象的属性:
w.setProperty('size',QSize(600,600))
print(w.property('size'))
Qt预定义了一些属性,详见Qt C++文档或PySide2(类似PyQt5的Python绑定)文档:https://doc.qt.io/qtforpython/api.html
也可以添加自定义的属性,使用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