I try to make a custom QPushButton with a stylesheet. I want to custom color of button when we mouse over it. It works, but I want to put a transition duration.
But in Qt this option is not available.
Here is my custom button:
#include "bouton.h"
Bouton::Bouton(QString title, QWidget *parent) : QPushButton()
{
setGeometry(50,50,120,40);
setText(title);
setMinimumHeight(30);
setParent(parent);
setStyleSheet(" QPushButton {"
"border-radius: 5px; "
"border: 1.5px solid rgb(91,231,255); "
"background-color: white; }"
"QPushButton:pressed {"
"border: 1.4px solid rgb(73,186,205); }"
"QPushButton:hover {"
"font-size: 16px;"
"transition: 0.9s; }");
}
The argument "transition 0.9s" doesn't work.
Here is an example in CSS.
Are there other ways to do this?
For some reason the proposed solution does not work as expected on Windows 10. I have updated the answer using painter.setOpacity(0.25); and painter.fillRect(rect(), m_currentColor); as a workaround. The code in the GitHub repository is updated as well.
QSS is not CSS. There is no transition property. Here is a list of all available properties.
Instead of using stylesheets, I would suggest you to take another path, which is longer, but gives you more flexibility. Here is the solution:
Create a subclass of QPushButton, e.g. AnimatedHoverButton
Get notified about QEvent::HoverEnter and QEvent::HoverLeave events by reimplementing QPushButton::event
bool AnimatedHoverButton::event(QEvent *event)
{
switch (event->type()) {
case QEvent::HoverEnter:
animateHover(true);
break;
case QEvent::HoverLeave:
animateHover(false);
break;
default:
break;
}
return QPushButton::event(event);
}
Create the in and out transition by using QVariantAnimation
void AnimatedHoverButton::animateHover(bool in)
{
if (m_transition)
m_transition->stop();
m_transition = new QVariantAnimation(this);
m_transition->setDuration(m_duration);
m_transition->setStartValue(m_currentColor);
m_transition->setEndValue(in ? palette().highlight().color()
: Qt::transparent);
connect(m_transition, &QVariantAnimation::valueChanged,
this, [this](const QVariant &value){
m_currentColor = value.value<QColor>();
repaint();
});
connect(m_transition, &QVariantAnimation::destroyed,
this, [this](){
m_transition = nullptr;
repaint();
});
m_transition->start(QAbstractAnimation::DeleteWhenStopped);
}
Paint the button by reimplementing the QPushButton::paintEvent event handler and taking into account the current value of the animation
void AnimatedHoverButton::paintEvent(QPaintEvent */*event*/)
{
QStylePainter painter(this);
QStyleOptionButton option;
initStyleOption(&option);
option.state &= ~QStyle::State_MouseOver;
painter.drawControl(QStyle::CE_PushButton, option);
painter.setOpacity(0.25);
painter.fillRect(rect(), m_currentColor);
}
Note: This solution uses the widget's palette to set the start and end values of the animation.
The solution might seem complicated, but fortunatelly I have prepared a working example for you of how to implement and use the AnimatedHoverButton class.
The following code fragment uses the AnimatedHoverButton class to produce a result, similar to the CSS example you have provided:
#include <QApplication>
#include "AnimatedHoverButton.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
AnimatedHoverButton button(QObject::tr("Hover Over Me"));
button.setTransitionDuration(300);
button.resize(300, 150);
button.show();
return a.exec();
}
The full code of the example is available on GitHub.
The given example produces the following result:

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With