使用 PyQt 闪烁小部件 [英] Blinking Widget with PyQt
问题描述
我只是想让 QDialog 中的一些元素闪烁(改变背景颜色).
I simply want some elements inside a QDialog to be blinking (altering background color).
现在最好我希望能够使用已经存在的东西并封装闪烁状态,即使用 css3 闪烁或者使用 QPropertyAnimation
可能?
Now preferably I'd like to be able to use something that already exists and encapsulates the blinking state, i.e. blinking with css3 or maybe it is possible with QPropertyAnimation
?
由于我没有找到有关该选项的任何好的信息,因此我尝试了不太理想的解决方案:
Since I didn't find any nice info on that option I tried the less optimal solution:
摘自对话__init__
:
self.timer = QTimer()
self.timer.timeout.connect(self.update_blinking)
self.timer.start(250)
self.last_blinked = None
和
def update_blinking(self):
self.frame.setStyleSheet(
self.STYLE_BLINK_ON if self.blink else self.STYLE_BLINK_OFF)
self.blink = not self.blink
其中 STYLE_BLINK_ON
和 STYLE_BLINK_OFF
是一些指定背景颜色的 css.那行得通,但是
where STYLE_BLINK_ON
and STYLE_BLINK_OFF
are some css specifying the background colors.
That works but
- 我觉得它超级难看,感觉就像 90 年代的代码
- 它不可用,因为频繁的样式更新会中断按钮点击.
对 2. 的解释:假设应该闪烁的小部件是一个框架.当单击该框架内的按钮时,如果在释放鼠标按钮之前发生框架的样式更新,则不会发出 clicked
信号.
Explanation for 2.: Assume the widget that should be blinking is a frame.
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.
一个完全不同的解决方案,它封装了一些东西,不需要我手动启动一个计时器,当然是首选.但如果有人至少提出解决第 2 点的解决方案,我将不胜感激.
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.
推荐答案
一种方法是使用 QPropertyAnimation
.QPropertyAnimation
对 Qt 属性进行插值 - 这个事实造成了困难:
The one way is to use QPropertyAnimation
. QPropertyAnimation
interpolates over Qt properties - this fact causes difficulties:
1) 通过样式表更改外观 -- 动画不能与字符串一起使用,因为它们不可插入.
1) Change appearance via style sheet -- animation cannot work with strings, because they're not interpolable.
2) 直接操作背景——背景颜色存储在QWidget.palette
的深处,它不是QProperty
.可能的解决方案是将背景颜色转换为小部件的属性:
2) Manipulate background directly -- background color is stored deep inside QWidget.palette
, it's not a 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)
另一种方法是处理QStateMachine
.他们能够操纵任何属性,而不仅仅是可插入的属性:
The other approach is dealing with QStateMachine
s. 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()
这篇关于使用 PyQt 闪烁小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!