可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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); }
回答1:
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.
回答2:
You can put your widgets into a QGraphicsScene
. It supports opacity changing and animation.
See QGraphicsProxyWidget
documentation for an example.
回答3:
Try expose some part of palette as property of label then animate it:
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); }
You can try avoid subclassing by defining and registering new interpolator which will handle QPalette qRegisterAnimationInterpolator, but this is a bit complicated.