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: