PyQt5,属性与属性动画

    技术2022-07-10  107

    0.前言

    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

    Processed: 0.010, SQL: 9