问题
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?
回答1:
Cause
QSS is not CSS. There is no transition property. Here is a list of all available properties.
Solution
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
andQEvent::HoverLeave
events by reimplementingQPushButton::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
andout
transition by using QVariantAnimationvoid 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<QColor>(); 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<QColor>(); 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 animationvoid 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.
Example
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.
Result
The given example produces the following result:
回答2:
You can use Animation.
MyButton.h
#include <QPushButton>
#include <QColor>
#include <QPropertyAnimation>
class MyButton : public QPushButton
{
Q_OBJECT
Q_PROPERTY(QColor color READ GetColor WRITE SetColor)
public:
explicit MyButton(QWidget *parent = 0);
void SetColor(const QColor& color);
const QColor& GetColor() const;
protected:
bool eventFilter(QObject *obj, QEvent *e);
private:
QColor m_currentColor;
QPropertyAnimation m_colorAnimation;
void StartHoverEnterAnimation();
void StartHoverLeaveAnimation();
};
MyButton.cpp
#include "MyButton.h"
#include <QEvent>
#include <QDebug>
MyButton::MyButton(QWidget *parent) :
QPushButton(parent),
m_colorAnimation(this, "color")
{
this->installEventFilter(this);
}
void MyButton::SetColor(const QColor& color)
{
m_currentColor = color;
QString css = "QPushButton { border-radius: 5px; ";
css.append("border: 1.5px solid rgb(91,231,255); ");
QString strColor = QString("rgb(%1, %2, %3)").arg(color.red()).arg(color.green()).arg(color.blue());
css.append("background-color: " + strColor + "; }");
setStyleSheet(css);
}
const QColor& MyButton::GetColor() const
{
return m_currentColor;
}
bool MyButton::eventFilter(QObject *obj, QEvent *e)
{
if (e->type() == QEvent::HoverEnter) {
StartHoverEnterAnimation();
}
if (e->type() == QEvent::HoverLeave) {
StartHoverLeaveAnimation();
}
return false;
}
void MyButton::StartHoverEnterAnimation()
{
m_colorAnimation.stop();
m_colorAnimation.setDuration(900); //set your transition
m_colorAnimation.setStartValue(GetColor()); //starts from current color
m_colorAnimation.setEndValue(QColor(100, 100, 100));//set your hover color
m_colorAnimation.setEasingCurve(QEasingCurve::Linear);//animation style
m_colorAnimation.start();
}
void MyButton::StartHoverLeaveAnimation()
{
m_colorAnimation.stop();
m_colorAnimation.setDuration(900); //set your transition
m_colorAnimation.setStartValue(GetColor()); //starts from current color
m_colorAnimation.setEndValue(QColor(255, 0, 0));//set your regular color
m_colorAnimation.setEasingCurve(QEasingCurve::Linear);//animation style
m_colorAnimation.start();
}
It will conflict with external qss setting. So set all qss in SetColor
.
来源:https://stackoverflow.com/questions/53084981/how-to-add-a-hover-transition-to-qpushbutton