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 standardQLabel
?QPropertyAnimation
, perhaps? -
@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. -
@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(); }
-
@Wieland
Nice example. I don't know why you usenew
so much, though ... ;) -
@kshegunov said:
I don't know why you use new so much
To avoid too many
#include
s 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. -
@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 ... :)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.
-
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.