2013-09-30 9 views
16

Sto provando a svanire e ad attenuare un QLabel o per qualsiasi sottoclasse QWidget. Ho provato con QGraphicsEffect, ma sfortunatamente funziona bene solo su Windows e non su Mac.Come far sbiadire o sfumare i widget Qt?

L'unica altra soluzione che può funzionare sia su Mac & di Windows sembra avere la mia personalizzato paintEvent dove ho impostato l'opacità di QPainter e anche definire un Q_PROPERTY per "opacità" nel mio derivato QLabel e modificare l'opacità attraverso QPropertyAnimation .

Sto incollando sotto lo snippet di codice pertinente come riferimento. Vedo ancora un problema qui - il riutilizzo del QLabel::paintEvent non sembra funzionare, funziona solo se eseguo un disegno personalizzato completo utilizzando lo QPainter, ma non sembra essere un modo semplice e se ho bisogno di farlo per ogni sottoclasse QWidget voglio svanire, è un incubo. Si prega di chiarire se sto facendo alcuni errori evidenti qui.

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); 
} 
+0

L'API Qt ti dice lo si usa in un modo che non doveva essere usato . I widget non sono davvero eccezionali se vuoi animare i loro contenuti in questo modo. Potrebbe funzionare per un proof-of-concept, ma a lungo termine dovresti usare Qt Quick. Sia che utilizzi Qt Quick 1 o Qt Quick 2 dipende da te, anche Qt Quick 1 (il modulo dichiarativo) sarebbe un miglioramento rispetto a quello che stai facendo. –

risposta

1

È possibile inserire i widget in un QGraphicsScene. Supporta il cambio di opacità e l'animazione.

Vedere la documentazione QGraphicsProxyWidget per un esempio.

1

Prova esporre una parte della gamma di colori di propietà della label poi animarlo:

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); 
} 

Si può provare a evitare di sottoclassi definendo e registrando nuovi interpolatore che si occuperà QPalette qRegisterAnimationInterpolator, ma questo è un po 'complicato.

20

C'è in realtà un modo molto semplice per fare questo senza intercettazioni QPaintEvent intercettazioni e senza i severi requisiti di QGraphicsProxyWidget, che non funziona su bambini widget promossi. La tecnica seguente funzionerà anche con i widget promossi e i relativi widget per bambini.

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.