PDA

View Full Version : Qt flickering animation



tomrider
1st May 2011, 07:34
Hi Everyone,
I have a problem creating a simple animation with Qt animation.
I have a small image located at the bottom right corner of the screen, i am trying to create animation that will enlarge the picture by streching it from the the top left corner of the image and streching it to the center of the screen.
I managed to do that, but, it's very notiable that qanimation makes it flicker (the right border of the picture, and it doesn't turns out good)
I also did that with no animation, but with a timer, and changing window geometry , but i had the same problem, seems that it's not refreshing fast enough, creating flickering in the right border of the picture.

here are the 2 examples:
1 - using property animation (geometery)

animation = new QPropertyAnimation(this, "geometry");
animation->setDuration(555);
animation->setEasingCurve(QEasingCurve::Linear);
animation->setStartValue(QRect(availableScreenSize.width()-minWidth-WINDOW_PADDING,availableScreenSize.height()-minHeight-WINDOW_PADDING,minWidth,minHeight));
animation->setEndValue(QRect(availableScreenSize.width()-maxWidth-WINDOW_PADDING,availableScreenSize.height()-maxHeight-WINDOW_PADDING,maxWidth,maxHeight));

2 - using a timer

#include "widget.h"
#include "ui_widget.h"
#include <QDesktopWidget>
#include <QDebug>

Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->setStyleSheet("background:transparent;");
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::Tool);

availableScreenSize = qApp->desktop()->availableGeometry();

//Growing from right to left
this->setGeometry(availableScreenSize.width()-165,availableScreenSize.height()-95,160,90);
//Growing from left to right
//this->setGeometry(200,200,160,90);

timeLine = new QTimeLine();
timeLine->setDuration(2222);
timeLine->setFrameRange(1, 800);
connect(timeLine, SIGNAL(frameChanged(int)), this, SLOT(update()));

counter = 0;

timeLine->start();
}

Widget::~Widget()
{
delete ui;
}

void Widget::paintEvent(QPaintEvent * /* event */)
{
counter++;
qDebug() << counter;

qApp->processEvents();
//Growing from right to left
this->setGeometry(availableScreenSize.width()-165-this->width()-1,availableScreenSize.height()-95-this->height()-1,this->width()+1,this->height()+1);

//Growing from left to right
//this->setGeometry(200,200,this->width()+1,this->height()+1);

if(timeLine->currentFrame() == 800)
{
qApp->exit(1);
}
}


Now the weired thing here is that if the animation is from left 2 right - it looks smooth... once the direction is changed from right 2 left the entire right border is "jumpy" .

I'll appriciate any help that you can give me.
Thanks!

wysota
4th May 2011, 19:33
Your paintEvent() is a complete junk. I'd start with fixing it.

tomrider
5th May 2011, 13:59
wysota,
Thank you for your helpful advice!
While thinking about your advice, i noticed that Qt is not that great with implementing the double buffering it suppose to do... i managed to overcome it by creating the animation inside a transparent larger window.
Although it's a crappy way (unlike your much helpfull advice) it works...
Also, i have given 2 different options - first one with qpropertyanimation , very simple and clean and still don't work.
If you don't know the answer - please don't leave unnecessary feedback
Thank you for your effort.

wysota
5th May 2011, 14:12
While thinking about your advice, i noticed that Qt is not that great with implementing the double buffering it suppose to do...
If you remove wheels from a car it is not much good at traveling either.


If you don't know the answer - please don't leave unnecessary feedback
I know your paintEvent is a junk and it is the one causing problems. If you are inside an event handler and you ask the framework to start handling events at that point (which it already is doing but you require it to loop again into the event queue and possibly reinitialize your widget which causes flickering) or you start resizing a widget when you are supposed to paint it (which causes a flicker as the widget is erased and then resized, erased again, resized, erased again and so on and is never drawn) then you are shooting yourself in the foot.

tomrider
5th May 2011, 14:25
Any insights on the qpropertyanimation and why it's not working?
Also, do you have any idea why double buffering is not preformed? do you have any alternatives?

p.s - regarding your answer - how do you explain that from left to right its working smoothly and when transfering the direction to right to left it's flickering?

wysota
5th May 2011, 14:31
Any insights on the qpropertyanimation and why it's not working?
It is working. See how the title bar of your window behaves -- it also "flickers" or rather "shakes" when the window gets resized and it is not drawn by Qt but by your window manager.

Also, do you have any idea why double buffering is not preformed? do you have any alternatives?
It is performed. When the window size changes it is the window manager's responsibility to expose the surface for the widget. That's what causes your flickering (the swap between the old surface and the new one) and that's why it works if you use an additional larger window that doesn't get resized -- as then double buffering is done solely by Qt. You can reduce the effect you have by disabling window decorations (by setting Qt::FramelessWindowHint) or complaining to your windowing system vendor to do something about it. If it was Qt that was causing the flicker, you'd be observing it on the entire area of the widget (as the widget is erased prior to being redrawn).