How to animate a qpushbutton background's gradient to go from left to right on hover?
Asked Answered
N

1

6

I'm practicing my programming skills and I am trying to build a login-system application with PyQt. I designed it after Login V4 . Now I'm trying to achieve that cool gradient animation from the Login button when you hover over it. But the CSS code to animate something like that doesn't work in qt stylesheet. I designed the app with the Qt Designer. Is it even possible to create that animation in pyqt? If yes, how do you that?

My app looks like this:

enter image description here

The stylesheet code of the Login button:

QPushButton#login_button {
font: 75 10pt "Microsoft YaHei UI";
font-weight: bold;
color: rgb(255, 255, 255);
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgb(61, 217, 245), stop:1 rgb(240, 53, 218));
border-style: solid;
border-radius:21px;
}
Norman answered 5/10, 2019 at 13:16 Comment(2)
I think it's doable if you change the start and stop colors of the gradient a few hundreds times in a loop upon cursor hovering. You might want to write a separate function that returns those, after taking in argument something like (color1, color2, shift_percentage). Do you see where I'm going?Synthetic
At 0% you have for example start=cyan, stop=magenta, then at 10% start=0.9*cyan+0.1*magenta, stop=0.9*magenta+0.1*cyan etc. and you update the stylesheet in a rapid succession. Of course replace cyan and magenta with their rgb equivalent.Synthetic
J
8

As you suspect, Qt Style Sheet does not support animations. In this case, an alternative is to use QXAnimation as QVariantAnimation:

from PyQt5 import QtCore, QtGui, QtWidgets


class LoginButton(QtWidgets.QPushButton):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setMinimumSize(60, 60)

        self.color1 = QtGui.QColor(240, 53, 218)
        self.color2 = QtGui.QColor(61, 217, 245)

        self._animation = QtCore.QVariantAnimation(
            self,
            valueChanged=self._animate,
            startValue=0.00001,
            endValue=0.9999,
            duration=250
        )

    def _animate(self, value):
        qss = """
            font: 75 10pt "Microsoft YaHei UI";
            font-weight: bold;
            color: rgb(255, 255, 255);
            border-style: solid;
            border-radius:21px;
        """
        grad = "background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop:{value} {color2}, stop: 1.0 {color1});".format(
            color1=self.color1.name(), color2=self.color2.name(), value=value
        )
        qss += grad
        self.setStyleSheet(qss)

    def enterEvent(self, event):
        self._animation.setDirection(QtCore.QAbstractAnimation.Forward)
        self._animation.start()
        super().enterEvent(event)

    def leaveEvent(self, event):
        self._animation.setDirection(QtCore.QAbstractAnimation.Backward)
        self._animation.start()
        super().enterEvent(event)

if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    w = QtWidgets.QWidget()
    lay = QtWidgets.QVBoxLayout(w)

    for i in range(5):
        button = LoginButton()
        button.setText("Login")
        lay.addWidget(button)
    lay.addStretch()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())
Jacalynjacamar answered 5/10, 2019 at 17:52 Comment(1)
I knew you will help me @eyllanesc, thank you so much, this helped me a lot! This is amazing, you are amazing! Can you tell me please where I can learn more about creating animations in pyqt ?Norman

© 2022 - 2024 — McMap. All rights reserved.