QPropertyAnimation not responding properly
-
Same result in release version.
-
Same result.
-
Ok, I ran this minimal example and I think I know what is going on:
#include <QApplication> #include <QTimer> #include <QGraphicsOpacityEffect> #include <QPropertyAnimation> #include <QShortcut> #include <QLabel> #include <QDebug> #include <QPixmap> #define SCREEN_LOCK_DELAY 60000 #define POPUP_DELAY 1500 #define FADEOUT_TIME 2500 class ScreenLockOverlay : public QLabel{ public: ScreenLockOverlay(QWidget* parent); private: void popup(); void fadeIn(); void fadeOut(); QTimer* showTimer; QTimer* autoLock; QGraphicsOpacityEffect* effect; QPropertyAnimation* inAnim; QPropertyAnimation* outAnim; }; ScreenLockOverlay::ScreenLockOverlay(QWidget* parent) : QLabel(parent) { setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::Tool); QPixmap overlayPix(100,100); overlayPix.fill(Qt::blue); setPixmap(overlayPix); setAttribute(Qt::WA_TranslucentBackground); showTimer = new QTimer(this); connect(showTimer, &QTimer::timeout, this, &ScreenLockOverlay::fadeOut); autoLock = new QTimer(this); connect(autoLock, &QTimer::timeout, this, &ScreenLockOverlay::popup); //autoLock->start(SCREEN_LOCK_DELAY); connect(new QShortcut(Qt::Key_L, parent), &QShortcut::activated, this, &ScreenLockOverlay::popup); effect = new QGraphicsOpacityEffect(this); this->setGraphicsEffect(effect); inAnim = new QPropertyAnimation(effect, "opacity"); inAnim->setDuration(FADEOUT_TIME); inAnim->setStartValue(0); inAnim->setEndValue(1); inAnim->setEasingCurve(QEasingCurve::InBack); outAnim = new QPropertyAnimation(effect, "opacity"); outAnim->setDuration(FADEOUT_TIME); outAnim->setStartValue(1); outAnim->setEndValue(0); outAnim->setEasingCurve(QEasingCurve::OutBack); connect(outAnim, &QPropertyAnimation::finished, this, [=] () { hide(); qDebug() << "done"; }); hide(); } void ScreenLockOverlay::popup() { Q_ASSERT(parent()); const QWidget* const parentWid = static_cast<const QWidget*>(parent()); QPoint start = parentWid->mapToGlobal(QPoint(0,0)); move(start.x() + parentWid->width()/2 - width()/2, start.y() + parentWid->height() - height()); show(); showTimer->start(POPUP_DELAY); } void ScreenLockOverlay::fadeIn() { inAnim->start(); } void ScreenLockOverlay::fadeOut() { showTimer->stop(); outAnim->start(); } int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget wid; ScreenLockOverlay *lock = new ScreenLockOverlay(&wid); wid.show(); return a.exec(); }It's due to you using
QEasingCurve::OutBackandQEasingCurve::InBackwhich make little sense when operating opacity (opacity can never go above 100% or below 0%). The period when the animation goes above 1 or below 0 you interpret as "delay".
Regarding the "And sometimes it doesn't appear at all" you need to make sure the 2 animations are not running at the same time. At the moment if you start thefadeInbefore thefadeOutfully completed theshow()will almost immediately be overwritten by thehide.So to fix this:
- use a easing curve that actually make sense (e.g.
QEasingCurve::Linear) - before starting a
fadeIn/fadeOutyou should check if another animation is running and amend accordingly
- use a easing curve that actually make sense (e.g.
-
@VRonin said in QPropertyAnimation not responding properly:
Linear
That makes sense.
Something changed - when using a linear curve - but still not good.
I guess that when the finished() signal is emitted, then I can start a new animation?
Should I reuse the QPropertyAnimation instead of using QPropertyAnimation::DeleteWhenStopped? -
@VRonin said in QPropertyAnimation not responding properly:
Linear
That makes sense.
Something changed - when using a linear curve - but still not good.
I guess that when the finished() signal is emitted, then I can start a new animation?
Should I reuse the QPropertyAnimation instead of using QPropertyAnimation::DeleteWhenStopped?@Jakob-Clausen said in QPropertyAnimation not responding properly:
Should I reuse the QPropertyAnimation instead of using QPropertyAnimation::DeleteWhenStopped?
I would, no need to reallocate every time.
Something changed - when using a linear curve - but still not good.
Did you address the second point?
before starting a fadeIn/fadeOut you should check if another animation is running and amend accordingly
-
Yes. I only did it manually. I start the next animation with the hit of a key, when i get "done" in the output window.
I will automate it, but could that be the problem? -
Yes. I only did it manually. I start the next animation with the hit of a key, when i get "done" in the output window.
I will automate it, but could that be the problem?@Jakob-Clausen said in QPropertyAnimation not responding properly:
but could that be the problem?
It is, as mentioned above
-
Ok. Now the code looks like this.
I have prevented i from getting started, when something is running.#include "ScreenLockOverlay.h" #include <QTimer> #include <QGraphicsOpacityEffect> #include <QPropertyAnimation> #include "Resources/PanelControl.h" #include "Widgets/ButtonWidget.h" #include <QShortcut> #include <QDebug> #define SCREEN_LOCK_DELAY 60000 #define POPUP_DELAY 1500 #define FADEOUT_TIME 2500 ScreenLockOverlay::ScreenLockOverlay(QWidget* parent) : QLabel(parent), parent(parent), locked(false), running(false) { setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::Tool); setPixmap(Pixmap::pixmap(Pixmap::LOCK_OVERLAY)); setAttribute(Qt::WA_TranslucentBackground); showTimer = new QTimer(this); connect(showTimer, &QTimer::timeout, this, &ScreenLockOverlay::fadeOut); showTimer->setSingleShot(true); autoLock = new QTimer(this); connect(autoLock, &QTimer::timeout, this, &ScreenLockOverlay::popup); autoLock->start(SCREEN_LOCK_DELAY); connect(new QShortcut(Qt::Key_L, parent), &QShortcut::activated, this, &ScreenLockOverlay::popup); effect = new QGraphicsOpacityEffect(this); this->setGraphicsEffect(effect); animation = new QPropertyAnimation(effect, "opacity"); animation->setDuration(FADEOUT_TIME); animation->setEasingCurve(QEasingCurve::Linear); hide(); } void ScreenLockOverlay::swipe(bool state) { if (!locked) return; popup(); if (state) { locked = false; autoLock->start(SCREEN_LOCK_DELAY); } } void ScreenLockOverlay::popup() { if (running) return; autoLock->stop(); QPoint start = parent->mapToGlobal(QPoint(0,0)); move(start.x() + parent->width()/2 - width()/2, start.y() + parent->height() - height()); show(); locked = true; showTimer->start(POPUP_DELAY); } void ScreenLockOverlay::fadeIn() { animation->setStartValue(0); animation->setEndValue(1); animation->start(QPropertyAnimation::KeepWhenStopped); } void ScreenLockOverlay::fadeOut() { showTimer->stop(); animation->setStartValue(1); animation->setEndValue(0); running = true; animation->start(QPropertyAnimation::KeepWhenStopped); connect(animation, &QPropertyAnimation::finished, this, [=] () { hide(); running = false; qDebug() << "done" << endl; }); } -
But - now it looks like it is the calling of show() before the timer starts, that is delayed.
show() is called right away, but it takes a little while before the pixmap is actually shown.
What does that mean? -
But - now it looks like it is the calling of show() before the timer starts, that is delayed.
show() is called right away, but it takes a little while before the pixmap is actually shown.
What does that mean?@Jakob-Clausen said in QPropertyAnimation not responding properly:
show() is called right away, but it takes a little while before the pixmap is actually shown.
Isn't this what you want? the opacity starts at 0 so invisible, it take a while before becoming visible
-
No. It should be shown right away, and stay there a little, and then fade away.