Making QLabel fade out the current text and fade in the new one when setText is called



  • I want any text change via setText to be done via transparency animation instead of immediate change. Is that doable with a standard QLabel? QPropertyAnimation, perhaps?


  • Qt Champions 2016

    @Violet-Giraffe
    QPropertyAnimation over a QGraphicsOpacityEffect would be the first thing I'd try. It should work with a generic label, or with any widget.


  • Moderators

    @Violet-Giraffe Hi! @kshegunov's post hints into the right direction. You can't use QPropertyAnimation to interpolate between two strings but you can create a custom widget with two overlapping labels and use QProperyAnimation and QGraphicsOpacityEffect to animate the fading between the two labels. Something like:

    fadinglabel.h

    #ifndef FADINGLABEL_H
    #define FADINGLABEL_H
    
    #include <QWidget>
    #include <QString>
    
    class QLabel;
    class QGraphicsOpacityEffect;
    class QPropertyAnimation;
    
    class FadingLabel : public QWidget
    {
        Q_OBJECT
    public:
        explicit FadingLabel(QWidget *parent = 0);
    
        void setText(const QString &text);
    
    private:
        QLabel *m_label_back;
        QLabel *m_label_front;
        QGraphicsOpacityEffect *m_effect_back;
        QGraphicsOpacityEffect *m_effect_front;
        QPropertyAnimation *m_animation_back;
        QPropertyAnimation *m_animation_front;
    };
    
    #endif // FADINGLABEL_H
    

    fadinglabel.cpp

    #include "fadinglabel.h"
    
    #include <QHBoxLayout>
    #include <QLabel>
    #include <QGraphicsOpacityEffect>
    #include <QPropertyAnimation>
    
    FadingLabel::FadingLabel(QWidget *parent)
        : QWidget(parent)
    {
        QHBoxLayout *layout = new QHBoxLayout;
        this->setLayout(layout);
        m_label_back = new QLabel(this);
        m_label_front = new QLabel(this);
    
        m_effect_back = new QGraphicsOpacityEffect();
        m_effect_back->setOpacity(0.0f);
        m_label_back->setGraphicsEffect(m_effect_back);
    
        m_effect_front = new QGraphicsOpacityEffect();
        m_effect_front->setOpacity(1.0f);
        m_label_front->setGraphicsEffect(m_effect_front);
    
        m_animation_back = new QPropertyAnimation(m_effect_back, "opacity");
        m_animation_back->setDuration(1000);
        m_animation_back->setStartValue(1.0f);
        m_animation_back->setEndValue(0.0f);
    
        m_animation_front = new QPropertyAnimation(m_effect_front, "opacity");
        m_animation_front->setDuration(1000);
        m_animation_front->setStartValue(0.0f);
        m_animation_front->setEndValue(1.0f);
    }
    
    void FadingLabel::setText(const QString &text)
    {
        m_label_back->setText( m_label_front->text() );
        m_label_front->setText( text );
        m_animation_back->start();
        m_animation_front->start();
    }
    

  • Qt Champions 2016

    @Wieland
    Nice example. I don't know why you use new so much, though ... ;)


  • Moderators

    @kshegunov said:

    I don't know why you use new so much

    To avoid too many #includes in the header. An actual implementation for production would use pimpl idiom.



  • Thanks for the suggestions, colleagues! Let me try and see if I can make it work in my project.
    Not sure if optimal, but certainly a clever idea with two labels.

    Just my two cents: while I do try to minimize the number of #include in my headers as well, I wouldn't pay it too much attention. And PIMPL definitely makes for bloated code that's a bit harder to debug and maintain. Not much, but it is inconvenient. So I don't ever use it anymore without a really good reason.


  • Qt Champions 2016

    @Wieland said:

    To avoid too many #includes in the header. An actual implementation for production would use pimpl idiom.

    I was just teasing. ;)
    Still that's not a good argument, as you include the headers in the source already, and forward declare the classes ... :)

    @Violet-Giraffe

    So I don't ever use it anymore without a really good reason.

    If you're writing an application it's of no consequence. If you're writing a library on the other hand it's a good idea to keep binary compatibility. You can either use PIMPL for that, or abstract classes and factories, which are much worse in my opinion.



  • Binary compatibility is not necessarily a concern. Another reason for using PIMPL would be preventing your internals (private declarations) from bleeding into the public API headers.


  • Qt Champions 2016

    @Violet-Giraffe

    Binary compatibility is not necessarily a concern.

    Depends on the viewpoint I suppose. When I have to use and build a library that's not binary compatible I often swear to high heavens. Not a fun thing rebuilding dependencies over dependencies just because that wasn't a consideration for the developer who wrote it ...

    Another reason for using PIMPL would be preventing your internals (private declarations) from bleeding into the public API headers.

    I agree. It does provide nice clean class interface.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.