How to make Qt widgets fade in or fade out?

Soumya Das picture Soumya Das · Sep 30, 2013 · Viewed 21.1k times · Source

I am trying to fade in and fade out a QLabel or for that matter any QWidget subclass. I have tried with QGraphicsEffect, but unfortunately it works well only on Windows and not on Mac.

The only other solution which can work on both Mac & Windows seems to be having my own custom paintEvent where I set the opacity of QPainter and also define a Q_PROPERTY for "opacity" in my derived QLabel and change the opacity through QPropertyAnimation.

I am pasting below the relevant code snippet for your reference. I still see an issue here - reusing the QLabel::paintEvent doesn't seem to be working, it works only if I do a complete custom painting using the QPainter, but that doesn't seem to be an easy way and if I need to do that for every QWidget subclass I want to fade out, that's a nightmare. Please clarify if I am doing any obvious mistakes here.

Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)

void MyLabel::setOpacity(qreal value) {
    m_Opacity = value;
    repaint();
}

void MyLabel::paintEvent((QPaintEvent *pe) {
    QPainter p;
    p.begin(this);
    p.setOpacity();
    QLabel::paintEvent(pe);
    p.end();
}

void MyLabel::startFadeOutAnimation() {
    QPropertyAnimation *anim = new QPropertyAnimation(this, "opacity");
    anim->setDuration(800);
    anim->setStartValue(1.0);
    anim->setEndValue(0.0);
    anim->setEasingCurve(QEasingCurve::OutQuad);
    anim->start(QAbstractAnimation::DeleteWhenStopped);
}

Answer

Volomike picture Volomike · Oct 7, 2015

There's actually a super easy way to do this without messy QPaintEvent intercepts and without the tough requirements of QGraphicsProxyWidget, which doesn't work on promoted widget children. The technique below will work even with promoted widgets and their children widgets.

Fade In Your Widget

// w is your widget
QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this);
w->setGraphicsEffect(eff);
QPropertyAnimation *a = new QPropertyAnimation(eff,"opacity");
a->setDuration(350);
a->setStartValue(0);
a->setEndValue(1);
a->setEasingCurve(QEasingCurve::InBack);
a->start(QPropertyAnimation::DeleteWhenStopped);

Fade Out Your Widget

// w is your widget
QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this);
w->setGraphicsEffect(eff);
QPropertyAnimation *a = new QPropertyAnimation(eff,"opacity");
a->setDuration(350);
a->setStartValue(1);
a->setEndValue(0);
a->setEasingCurve(QEasingCurve::OutBack);
a->start(QPropertyAnimation::DeleteWhenStopped);
connect(a,SIGNAL(finished()),this,SLOT(hideThisWidget()));
// now implement a slot called hideThisWidget() to do
// things like hide any background dimmer, etc.