Как добавить всплывающий переход к QPushButton?

Я пытаюсь сделать кастом QPushButton с таблицей стилей. Я хочу, чтобы пользовательский цвет кнопки, когда мы наведем на нее курсор. Это работает, но я хочу поставить продолжительность перехода.
Но в Qt эта опция недоступна.

Вот моя пользовательская кнопка:

#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; }");
}

Аргумент «переход 0.9s» не работает.

Вот пример в CSS.

Есть ли другие способы сделать это?

1

Решение

QSS не является CSS. Свойство перехода отсутствует. Вот это список всех доступных свойств.

Вместо того, чтобы использовать таблицы стилей, я бы предложил вам выбрать другой путь, который длиннее, но дает вам больше гибкости. Вот решение:

  1. Создать подкласс QPushButtonнапример, AnimatedHoverButton

  2. Получать уведомления о QEvent::HoverEnter а также QEvent::HoverLeave События путем переопределения 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);
    }
    
  3. Создать in а также out переход с помощью 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<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);
    }
    
  4. Нарисуйте кнопку, реализовав QPushButton::paintEvent обработчик событий и с учетом текущего значения анимации

    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);
    }
    

Замечания: Это решение использует палитру виджета для установки начального и конечного значений анимации.

Решение может показаться сложным, но, к счастью, я подготовил для вас рабочий пример того, как реализовать и использовать AnimatedHoverButton учебный класс.

Следующий фрагмент кода использует AnimatedHoverButton класс для получения результата, аналогичного CSS пример, который вы предоставили:

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);

Полный код примера доступен на GitHub.

Данный пример дает следующий результат:

Окно с выделенной пользовательской кнопкой

0

Другие решения

Ты можешь использовать Анимация.

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();
}

Это будет конфликтовать с настройкой внешнего qss. Так что установите все QSS в SetColor,

0

По вопросам рекламы [email protected]