简体   繁体   English

用PyQt闪烁小部件

[英]Blinking Widget with PyQt

I simply want some elements inside a QDialog to be blinking (altering background color). 我只是希望QDialog内的某些元素闪烁(更改背景颜色)。

Now preferably I'd like to be able to use something that already exists and encapsulates the blinking state, ie blinking with css3 or maybe it is possible with QPropertyAnimation ? 现在最好是我希望能够使用已经存在的东西并封装闪烁状态,即使用css3进行闪烁,或者可以使用QPropertyAnimation

Since I didn't find any nice info on that option I tried the less optimal solution: 由于我没有找到关于该选项的任何好信息,因此尝试了次优的解决方案:

excerpt from the Dialogs __init__ : 对话框__init__摘录:

self.timer = QTimer()
self.timer.timeout.connect(self.update_blinking)
self.timer.start(250)
self.last_blinked = None

and

def update_blinking(self):
    self.frame.setStyleSheet(
        self.STYLE_BLINK_ON if self.blink else self.STYLE_BLINK_OFF)
    self.blink = not self.blink

where STYLE_BLINK_ON and STYLE_BLINK_OFF are some css specifying the background colors. 其中STYLE_BLINK_ONSTYLE_BLINK_OFF是一些CSS,用于指定背景颜色。 That works but 那可行,但是

  1. I find it super ugly, it feels like code from the 90s 我觉得它非常丑陋,感觉就像90年代的代码
  2. It isn't usable as the frequent style-update interrupts button-clicks. 它不可用,因为频繁的样式更新会中断按钮单击。

Explanation for 2.: Assume the widget that should be blinking is a frame. 2.的解释:假设应该闪烁的小部件是一个框架。 When a button inside that frame is clicked, the clicked signal isn't emitted if a style-update of the frame occurs before the mouse-button is released. 单击该框架内的按钮时,如果在释放鼠标按钮之前发生了框架的样式更新,则不会发出clicked信号。

A completely different solution that encapsulates things and doesn't require me to manually start a timer would of course be preferred. 当然,首选完全不同的解决方案来封装事物,并且不需要我手动启动计时器。 But I would be grateful if someone at least came up with a solution which solves point 2. 但是,如果有人至少提出了解决第2点的解决方案,我将不胜感激。

The one way is to use QPropertyAnimation . 一种方法是使用QPropertyAnimation QPropertyAnimation interpolates over Qt properties - this fact causes difficulties: QPropertyAnimation对Qt属性进行插值 -这个事实引起了困难:

1) Change appearance via style sheet -- animation cannot work with strings, because they're not interpolable. 1)通过样式表更改外观-动画无法与字符串一起使用,因为它们不可插值。

2) Manipulate background directly -- background color is stored deep inside QWidget.palette , it's not a QProperty . 2)直接操作背景-背景颜色存储在QWidget.palette ,不是QProperty The possible solution is to transform background color into a widget's property: 可能的解决方案是将背景颜色转换为小部件的属性:

class AnimatedWidget(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)

        color1 = QtGui.QColor(255, 0, 0)
        color2 = QtGui.QColor(0, 255, 0)

        self.color_anim = QtCore.QPropertyAnimation(self, 'backColor')
        self.color_anim.setStartValue(color1)
        self.color_anim.setKeyValueAt(0.5, color2)
        self.color_anim.setEndValue(color1)
        self.color_anim.setDuration(1000)
        self.color_anim.setLoopCount(-1)
        self.color_anim.start()

    def getBackColor(self):
        return self.palette().color(QtGui.QPalette.Background)

    def setBackColor(self, color):
        pal = self.palette()
        pal.setColor(QtGui.QPalette.Background, color)
        self.setPalette(pal)

    backColor = QtCore.pyqtProperty(QtGui.QColor, getBackColor, setBackColor)

The other approach is dealing with QStateMachine s. 另一种方法是处理QStateMachine They're able to manipulate any properties, not only interpolable ones: 他们能够操纵任何属性,而不仅仅是可插值的属性:

class StateWidget(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)

        style1 = "background-color: yellow"
        style2 = "background-color: black"

        # animation doesn't work for strings but provides an appropriate delay
        animation = QtCore.QPropertyAnimation(self, 'styleSheet')
        animation.setDuration(150)

        state1 = QtCore.QState()
        state2 = QtCore.QState()
        state1.assignProperty(self, 'styleSheet', style1)
        state2.assignProperty(self, 'styleSheet', style2)
        #              change a state after an animation has played
        #                               v
        state1.addTransition(state1.propertiesAssigned, state2)
        state2.addTransition(state2.propertiesAssigned, state1)

        self.machine = QtCore.QStateMachine()
        self.machine.addDefaultAnimation(animation)
        self.machine.addState(state1)
        self.machine.addState(state2)
        self.machine.setInitialState(state1)
        self.machine.start()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM