vendredi 31 juillet 2020

How to visualize a QPushButton after hovering on a QLabel

How do I visualize a QPushButton after hovering on a QLabel?

Given a very simple user interface composed of a QLabel and a QComboBox shown below:

vis1

The user clicks on the QComboBox below (promoted as QPixmapComboBox), and a list of colors shows up. The user clicks one of this color and a QPixmapPopUp shows up. This QPixmapPopUp is also sub-classed as a QLabel to allow the override of the paintEvent. The popup shows up and after you hover on it it changes color. It was very difficult to arrive to this point for the small verifiable example. Problem: But now I got stuck because as I hover the popup, I have been trying to understand how to show two push button. Those buttons should also disappear as the user does not hover anymore on the popup. For completeness the whole minimal verifiable example can also be downloaded from here if needed:

Below the current behavior and the expected behavior:

Current Behavior:

vis2

Expected Behavior:

vis3

Below the most important part of the code where the animation and the paint event is taken care of: qpixmappopup.h

#include <QLabel>
#include <QTimer>
#include <QVariantAnimation>
#include <QStyleOptionButton>
#include <QStylePainter>
#include <QEvent>

class QPixmapPopUp : public QLabel
{
    Q_OBJECT
public:
    QPixmapPopUp(QWidget *parent = nullptr);
    void show(int msecs = 3000);

signals:
    void clicked();

protected:
    void mousePressEvent(QMouseEvent *e) override;
    void paintEvent(QPaintEvent *) override;
    
private:
    QTimer *mTimer;
    void animateHover(bool in);
    QVariantAnimation *m_transition;
    int m_duration;
    QColor m_currentColor;

};

qpixmappopup.cpp

#include "qpixmappopup.h"
#include <QMouseEvent>
#include <QStyleOptionButton>

QPixmapPopUp::QPixmapPopUp(QWidget *parent)
    : QLabel { parent }
{
    setFrameShape(QLabel::Box);
    setWindowFlag(Qt::Popup);
    setFocusPolicy(Qt::WheelFocus);
    mTimer = new QTimer(this);
    mTimer->setSingleShot(true);
    connect(mTimer, &QTimer::timeout, this, &QLabel::hide);
}

void QPixmapPopUp::show(int msecs)
{
    QLabel::show();
    mTimer->start(msecs);
}

void QPixmapPopUp::mousePressEvent(QMouseEvent *e)
{
    emit clicked();
    hide();
    QLabel::mousePressEvent(e);
}

void QPixmapPopUp::paintEvent(QPaintEvent *)
{
    QStylePainter painter(this);
    QStyleOptionButton option;
    QPalette p(palette());
    option.state |= QStyle::State_MouseOver;

}

void QPixmapPopUp::animateHover(bool in)
{
    const QColor &baseColor(palette().brush(QPalette::Light).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);
}

I have been doing extensive research on how to solve this problem and consulted this source which was good because it explained how the hovering should or should not occur.

I moved initially to re-implementation of the protected memebers void enterEvent(QEvent *ev) override and void leaveEvent(QEvent *ev) override found in this source, and thought it could have been a good idea moving in that direction. But after a bit of trial-error I arrived nowhere.

I tried to search as much as possible a possible solution in the official documentation of Qt5 but didn't really find any useful lead on how to move on from here.

Please if anyone had the same problem, point to the right solution on how to solve this issue as of now I don't have any additional idea on how to move on.

Aucun commentaire:

Enregistrer un commentaire