PyQt5 styleSheet 动画 [英] PyQt5 styleSheet Animation

查看:114
本文介绍了PyQt5 styleSheet 动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 PyQt5 构建一个带有多个按钮的应用程序.我想要完成的是为我的一些按钮创建一个闪烁的背景颜色(黄红色).

I am using PyQt5 to build an app with multiple buttons. What I am trying to accomplish is to create a blinking background color (yellow-red) for some of my buttons.

btn1.setStyleSheet("background-color: green; color: red; font-weight: 800; font-size: 22")
tobyte = 'styleSheet'
a = bytearray(tobyte, 'utf-8')
animation = QtCore.QPropertyAnimation(' + 'btn' + str(yy) + ', a)
animation.setDuration(1000)
animation.setLoopCount(1000)
animation.setStartValue("background-color: yellow; color: red; font-weight: 800; font-size: 22")
animation.setEndValue("background-color: red; color: red; font-weight: 800; font-size: 22")
animation.start()

动画开始(移除预定义的绿色背景),但不会将按钮的背景颜色更改为黄色或红色.

The animation starts (it removes the predefined, green background), but it doesn't change the background color of the button to yellow or red.

有什么想法吗?

推荐答案

您不应该对样式表进行动画处理,因为存在必须对特定值进行动画处理(插值)的模糊性.PyQt5 类中没有样式表的内部解析器.尽管如此,还是有办法解决这个问题的.下面是动画 QLabel 的工作示例(QLabel 的背景颜色).

You ought not to animate stylesheets because there are the vagueness which specifically value must be animated (interpolated). There are not internal parser of stylesheet into PyQt5 classes. Nevertheless there are ways to solve the problem. Below is working example for animated QLabel (background-color of QLabel).

主要思想在于使用自定义QtCore.QPropertyAnimation.在这种情况下,它的名称是 zcolor.此外,您应该在从 QLabel(和任何其他类)派生的类中创建属性 QtCore.pyqtProperty.

Main idea consists in using the custom QtCore.QPropertyAnimation. In this case its name is zcolor. Also you ought to create property QtCore.pyqtProperty in class derived from QLabel (and any other class).

此外,您可以在类中使用多个动画,例如您可以在三种动画类型(无动画、类型 1、类型 2)之间切换.

Moreover you can use several animation in your class, in example you can switch between three types of animation (No animation, type 1, type 2).

当然,some 小部件的 some 参数可以通过 QtGui.QPalette.Window 进行动画处理,无需解析 ss(请参阅注释中的三个字符串从 # pal = self.palette()) 开始,但是恕我直言,通过样式表的方式更灵活.

Of course some params of some widgets can be animated via QtGui.QPalette.Window without parse of ss (see three strings in comment starting with # pal = self.palette()), however the way via stylesheets is more flexible IMHO.

import sys
import re

from PyQt5.QtWidgets import (QApplication, QFormLayout, QLabel, QDialog, QLineEdit, QPushButton)

from PyQt5 import QtCore, QtGui


class AnimatedLabel(QLabel):
    def __init__(self):
        QLabel.__init__(self)

        color1 = QtGui.QColor(255, 0, 0)
        color2 = QtGui.QColor(255, 144, 0)
        color3 = QtGui.QColor(255, 255, 0)
        color4 = QtGui.QColor(224, 192, 192)

        color5 = QtGui.QColor(192, 224, 192)
        color6 = QtGui.QColor(192, 192, 192)
        color7 = QtGui.QColor(212, 208, 200)

        self.co_get = 0
        self.co_set = 0

        byar = QtCore.QByteArray()
        byar.append('zcolor')
        self.color_anim = QtCore.QPropertyAnimation(self, byar)
        self.color_anim.setStartValue(color4)
        self.color_anim.setKeyValueAt(0.15, color1)
        self.color_anim.setKeyValueAt(0.3, color2)
        self.color_anim.setKeyValueAt(0.5, color3)
        self.color_anim.setKeyValueAt(0.75, color2)
        self.color_anim.setEndValue(color4)
        self.color_anim.setDuration(2000)
        self.color_anim.setLoopCount(1)

        self.color_anim_ok = QtCore.QPropertyAnimation(self, byar)
        self.color_anim_ok.setStartValue(color5)
        self.color_anim_ok.setKeyValueAt(0.5, color6)
        self.color_anim_ok.setEndValue(color7)
        self.color_anim_ok.setDuration(1000)
        self.color_anim_ok.setLoopCount(-1)

        self.custom_anim = QtCore.QPropertyAnimation(self, byar)

    def parseStyleSheet(self):
        ss = self.styleSheet()
        sts = [s.strip() for s in ss.split(';') if len(s.strip())]
        return sts

    def getBackColor(self):
        self.co_get += 1
        # print(fuin(), self.co_get)
        return self.palette().color(self.pal_ele)

    def setBackColor(self, color):
        self.co_set += 1
        sss = self.parseStyleSheet()
        bg_new = 'background-color: rgba(%d,%d,%d,%d);' % (color.red(), color.green(), color.blue(), color.alpha())

        for k, sty in enumerate(sss):
            if re.search('\Abackground-color:', sty):
                sss[k] = bg_new
                break
        else:
            sss.append(bg_new)

        # pal = self.palette()
        # pal.setColor(self.pal_ele, color)
        # self.setPalette(pal)
        self.setStyleSheet('; '.join(sss))

    pal_ele = QtGui.QPalette.Window
    zcolor = QtCore.pyqtProperty(QtGui.QColor, getBackColor, setBackColor)


# this class is only for test
class SomeDia2(QDialog):
    def __init__(self, parent=None):
        """Sets up labels in form"""
        QDialog.__init__(self, parent)

        self.co_press = 0

        self.setModal(True)
        self.setWindowTitle('Animation Example')

        self.edit_pad =  QLineEdit('-1')
        self.edit_rad =  QLineEdit('-1')
        self._mapHeight = QLineEdit('0')

        self.layout = QFormLayout()
        self.lab_pad = QLabel('Padding (px):')
        self.lab_rad = QLabel('Radius (px):' )
        self.layout.addRow(self.lab_pad, self.edit_pad)
        self.layout.addRow(self.lab_rad, self.edit_rad)

        self.anila = AnimatedLabel()
        self.anila.setText('Label for animation:')
        # self.anila.setStyleSheet('padding: 0 4px; border-radius: 4px;')
        self.layout.addRow(self.anila, self._mapHeight)

        self.ok = QPushButton()
        self.ok.setText('OK -- change animation')
        self.ok.clicked.connect(self._okPress)

        self.layout.addRow(self.ok)
        self.layout.setLabelAlignment(QtCore.Qt.AlignRight)

        self.setLayout(self.layout)
        self.set_initial_data()

    def set_initial_data(self):
        pad_vali = QtGui.QIntValidator(0, 20)
        rad_vali = QtGui.QIntValidator(0, 10)

        self.edit_pad.setValidator(pad_vali)
        self.edit_rad.setValidator(rad_vali)

        pad, rad = 4, 4
        self.edit_pad.setText(str(pad))
        self.edit_rad.setText(str(rad))

        self.set_ss(pad,rad)

        # slots
        self.edit_pad.textChanged.connect(self.change_padrad)
        self.edit_rad.textChanged.connect(self.change_padrad)

    def set_ss(self, pad, rad):
        self.anila.setStyleSheet('padding: 0 %dpx; border-radius: %dpx;' % (pad, rad))
        for lab in [self.lab_rad, self.lab_pad]:
            lab.setStyleSheet('padding: 0 %dpx;' % pad)

    def change_padrad(self):
        try:
            pad = int(self.edit_pad.text())
            rad = int(self.edit_rad.text())
            # print(pad, rad)
            self.set_ss(pad, rad)
        except Exception as ex:
            print(type(ex).__name__)

    def _okPress(self, flag):
        # print('OK PRESS', flag)
        self.co_press += 1
        typ = self.co_press % 3
        if 0 == typ:
            print('Animation NO')
            self.anila.color_anim.stop()
            self.anila.color_anim_ok.stop()
        elif 1 == typ:
            print('Animation type 1')
            self.anila.color_anim_ok.stop()
            self.anila.color_anim.start()
        elif 2 == typ:
            print('Animation type 2')
            self.anila.color_anim.stop()
            self.anila.color_anim_ok.start()


if __name__ == "__main__":

    app = QApplication(sys.argv)

    dia = SomeDia2()
    dia.show()

    app.exec_()

这篇关于PyQt5 styleSheet 动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆