“Blinking” buttons in PyQT5

蹲街弑〆低调 提交于 2020-12-15 10:24:36

问题


Here's the deal: I'm trying to make button A "blink" when button B is pushed, and the blinking should then stop when the user pushes button A. Furthermore, button A should then go back to its former state.

After long reading through the documentation and other questions at SO, I have now following piece of code:

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_()

The code itself I got mostly from @Alexander Lutsenko in this 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 this other question it only provides a colorful border to the QPushButton. And I'm fine with that, it doesn´t look that intrusive.

The problem

After starting the animation, if I push the Stop button, the button doesn't go back to its original state (with no colorful border), but stays with the color of the animation at the time the Stop button was pressed.

Furthermore, I get following warning:

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

But the script keeps running and the animation going, so that doesn't break anything.

The question

How do I "reset" the styleSheet of the button properly? Is there another (maybe better and pythonic) way to do the blinking button stuff? Thanks a lot!


回答1:


The property does not save the initial state so even if you pair the animation it will not be restored to the initial state. So the solution in this case is to save that state in a variable and create a reset_color() method that restores the color again..

On the other hand the error message: TypeError: unable to convert to Python 'QBrush' object to a C ++ 'QColor' instance indicates that the code self.button_stop.palette().base() returns a QBrush, but it is expected a QColor, and there is no conversion implied, so that implementation must be changed.

As a matter of order I will create a new class that inherits from QPushButton and implement those properties.

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_()


来源:https://stackoverflow.com/questions/50725166/blinking-buttons-in-pyqt5

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!