您当前的位置: 首页 >  动画

龚建波

暂无认证

  • 1浏览

    0关注

    313博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

PyQt5,属性与属性动画

龚建波 发布时间:2020-06-30 23:36:24 ,浏览量:1

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

关注
打赏
1655829268
查看更多评论
立即登录/注册

微信扫码登录

0.2771s