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.
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;
}
return QPushButton::event(event);
}
Create the in
and out
transition by using QVariantAnimation
void AnimatedHoverButton::animateHover(bool in)
{
const QColor &baseColor(palette().brush(QPalette::Button).color());
const QColor &highlightColor(palette().brush(QPalette::Highlight).color());
QColor startValue(in ? baseColor : highlightColor);
if (m_transition) {
startValue = m_transition->currentValue().value();
m_transition->stop();
}
m_transition = new QVariantAnimation(this);
m_transition->setStartValue(startValue);
m_transition->setEndValue(in ? highlightColor : baseColor);
m_transition->setDuration(m_duration);
connect(m_transition, &QVariantAnimation::valueChanged, [this](const QVariant &value){
m_currentColor = value.value();
repaint();
});
connect(m_transition, &QVariantAnimation::destroyed, [this](){
m_transition = nullptr;
});
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;
QPalette p(palette());
initStyleOption(&option);
p.setBrush(QPalette::Button, m_currentColor);
option.palette = p;
option.state |= QStyle::State_MouseOver;
painter.drawControl(QStyle::CE_PushButton, option);
}
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:
auto *button = new AnimatedHoverButton(tr("Hover Over Me"), this);
QPalette p(button->palette());
p.setBrush(QPalette::Button, QColor("#F89778"));
p.setBrush(QPalette::ButtonText, QColor("#FFFFFF"));
p.setBrush(QPalette::Highlight, QColor("#F4511E"));
button->setPalette(p);
button->setTransitionDuration(300);
setCentralWidget(button);
setContentsMargins(10, 10, 10, 10);
The full code of the example is available on GitHub.
The given example produces the following result: