"Blinking" PyQT5 中的按钮

"Blinking" buttons in PyQT5

事情是这样的:我正在尝试在按下按钮 B 时使按钮 A "blink",然后当用户按下按钮 A 时闪烁应该停止。此外,按钮 A 应该返回到它以前的状态。

在 SO 阅读文档和其他问题后,我现在有以下代码:

Python 2.7

class Widget(QWidget):

    def __init__(self):
        super(Widget, self).__init__()

        self.resize(300,200)
        layout = QVBoxLayout(self)


        self.button_stop = QPushButton("Stop")
        layout.addWidget(self.button_stop)

        self.button_start = QPushButton("Start", self)
        layout.addWidget(self.button_start)

        self.animation = QPropertyAnimation(self, "color", self)
        self.animation.setDuration(1000)
        self.animation.setLoopCount(100)
        self.animation.setStartValue(self.color)
        self.animation.setEndValue(self.color)
        self.animation.setKeyValueAt(0.1, QColor(0,255,0))

        self.button_start.clicked.connect(self.animation.start)
        self.button_stop.clicked.connect(lambda: self.stop())

    def stop(self):
        self.animation.stop()
        self.button_stop.setStyleSheet("")

    def getColor(self):
        return self.button_stop.palette().base()

    def setColor(self, color):
        palette = self.button_stop.palette()
        palette.setColor(self.button_stop.backgroundRole(), color)
        self.button_stop.setAutoFillBackground(True)
        self.button_stop.setPalette(palette)


    color = pyqtProperty(QColor, getColor, setColor)


if __name__ == "__main__":
    app = QApplication([])
    w = Widget()
    w.show()
    app.exec_()

代码本身主要来自 question, with a few modifications here and there to test my needs. The main part ist straightforward: I create a window with two QPushButton, one to start the QPropertyAnimation and the other one to stop it. The QPropertyAnimation itself is applied to one of the buttons. It should in theory change the background color of the button, but due to the limitations explained in 中的@Alexander Lutsenko,它只为 QPushButton 提供了彩色边框。我对此很好,它看起来没有那么打扰。

问题

动画开始后,如果我按下 Stop 按钮,按钮不会回到原来的状态(没有彩色边框),而是保持动画当时的颜色Stop 按钮被按下。

此外,我收到以下警告:

TypeError: unable to convert a Python 'QBrush' object to a C++ 'QColor' instance

但脚本保持 运行 和动画继续运行,因此不会破坏任何东西。

问题

如何"reset" 正确地设置按钮的样式表?是否有另一种(也许更好和 pythonic)方法来做闪烁按钮的事情?非常感谢!

属性不保存初始状态所以即使配对动画也不会恢复到初始状态。所以在这种情况下的解决方案是将该状态保存在一个变量中并创建一个 reset_color() 方法来再次恢复颜色..

另一方面,错误消息:TypeError: unable to convert to Python 'QBrush' object to a C ++ 'QColor' instance 表示代码 self.button_stop.palette().base() returns 是 QBrush,但预期是 QColor,并且没有隐含的转换,因此必须更改实现。

作为顺序问题,我将创建一个继承自 QPushButton 的新 class 并实现这些属性。

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class BlinkButton(QPushButton):
    def __init__(self, *args, **kwargs):
        QPushButton.__init__(self, *args, **kwargs)
        self.default_color = self.getColor()

    def getColor(self):
        return self.palette().color(QPalette.Button)

    def setColor(self, value):
        if value == self.getColor():
            return
        palette = self.palette()
        palette.setColor(self.backgroundRole(), value)
        self.setAutoFillBackground(True)
        self.setPalette(palette)

    def reset_color(self):
        self.setColor(self.default_color)

    color = pyqtProperty(QColor, getColor, setColor)


class Widget(QWidget):

    def __init__(self):
        super(Widget, self).__init__()

        self.resize(300,200)
        layout = QVBoxLayout(self)

        self.button_stop = BlinkButton("Stop")
        layout.addWidget(self.button_stop)

        self.button_start = QPushButton("Start", self)
        layout.addWidget(self.button_start)

        self.animation = QPropertyAnimation(self.button_stop, "color", self)
        self.animation.setDuration(1000)
        self.animation.setLoopCount(100)
        self.animation.setStartValue(self.button_stop.default_color)
        self.animation.setEndValue(self.button_stop.default_color)
        self.animation.setKeyValueAt(0.1, QColor(0,255,0))

        self.button_start.clicked.connect(self.animation.start)
        self.button_stop.clicked.connect(self.stop)

    def stop(self):
        self.animation.stop()
        self.button_stop.reset_color()

if __name__ == "__main__":
    app = QApplication([])
    w = Widget()
    w.show()
    app.exec_()