¿Cómo hacer que los widgets Qt se atenúen o desaparezcan?
animation opacity (3)
Estoy tratando de desvanecer y desvanecer un QLabel
o, en QWidget
cualquier subclase de QWidget
. He intentado con QGraphicsEffect
, pero desafortunadamente solo funciona bien en Windows y no en Mac.
La única otra solución que puede funcionar tanto en Mac como en Windows parece ser tener mi propio paintEvent
personalizado donde establezco la opacidad de QPainter
y también defino una Q_PROPERTY
para "opacidad" en mi QLabel
derivado y cambio la opacidad mediante QPropertyAnimation
.
Estoy pegando debajo del fragmento de código relevante para su referencia. Sigo viendo un problema aquí: reutilizar QLabel::paintEvent
no parece funcionar, solo funciona si hago una pintura personalizada completa con QPainter
, pero no parece ser una manera fácil y si necesito hacer eso para cada subclase de QWidget
que quiero desvanecer, es una pesadilla. Por favor, aclare si estoy haciendo algún error obvio aquí.
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);
}
En realidad, hay una manera muy fácil de hacer esto sin las intercepciones desordenadas de QPaintEvent
y sin los requisitos QGraphicsProxyWidget
de QGraphicsProxyWidget
, que no funciona en los niños de widgets promocionados. La siguiente técnica funcionará incluso con los widgets promocionados y los widgets de sus hijos.
Desvanecerse en su 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);
Desvanece tu 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.
Intente exponer una parte de la paleta como propiedad de la etiqueta y luego anímela:
Q_PROPERTY(QColor color READ color WRITE setColor)
void MyLabel::setColor(const QColor &value) {
QPalette palette;
palette.setBrush(QPalette::WindowText, value);
setPalette(palette);
}
QColor MyLabel::color() {
return palette(QPalette::Normal, QPalette::Window).
}
void MyLabel::startFadeOutAnimation() {
QPropertyAnimation *animation = new QPropertyAnimation(label, "color", this);
QColor c = label->color();
animation->setKeyValueAt(0, c);
c.setAlpha(0);
animation->setKeyValueAt(1, c);
animation->setEasingCurve(QEasingCurve::OutQuad);
animation->setDuration(1000);
animation->start(QAbstractAnimation::DeleteWhenStopped);
}
Puede intentar evitar las subclases definiendo y registrando un nuevo interpolador que manejará QPalette qRegisterAnimationInterpolator , pero esto es un poco complicado.
Puedes poner tus widgets en un QGraphicsScene
. Soporta cambio de opacidad y animación.
Consulte la documentación de QGraphicsProxyWidget
para ver un ejemplo.