PDA

View Full Version : Qwidget Animation with Qtimer



tissa
17th June 2014, 00:10
I want to make an animation with two circlewidget in a scene. My purpose is to make the first widget with concentric circle animated for a periode of time and then stop it, after make the second widget animated also for a periode of time .

but I get blocked how to make such thing here is my code:

Main.cpp:


#include <QApplication>

#include <QTimer>
#include<unistd.h>
#include<QGraphicsScene>
#include<QGraphicsProxyWidget>
#include<QGraphicsView>
#include "circlewidget.h"
#include<QTimeLine>


int main(int argc, char *argv[])
{

QApplication app(argc, argv);
CircleWidget * circle= new CircleWidget();
CircleWidget * circl= new CircleWidget();
QGraphicsScene scene;


QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget();
proxy->setWidget(circle);
proxy->setPos(0,1);

scene.addItem(proxy);
QTimer * time=new QTimer();
QTimer * timer=new QTimer();

QGraphicsProxyWidget *prox = new QGraphicsProxyWidget();
prox->setWidget(circl);
prox->setPos(200,100);
scene.addItem(prox);

/*QTimeLine *timer = new QTimeLine(5000);
timer->setFrameRange(0, 100);*/

QGraphicsView view(&scene);



QObject::connect(timer, SIGNAL(timeout()), circl, SLOT(nextAnimationFrame()));
timer->start();
sleep(5);
timer->stop();
QObject::connect(time, SIGNAL(timeout()),circle, SLOT(nextAnimationFrame()));
time->start();
view.show();



return app.exec();

}

circlewidget.cpp:


#include <QtGui>

#include "circlewidget.h"
#include<unistd.h>
#include <stdlib.h>

CircleWidget::CircleWidget(QWidget *parent)
: QWidget(parent)
{


setBackgroundRole(QPalette::Base);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

}


QSize CircleWidget::minimumSizeHint() const
{
return QSize(50, 50);
}

QSize CircleWidget::sizeHint() const
{
return QSize(180, 180);
}

void CircleWidget::nextAnimationFrame()
{

update();
++ frameNo;

}


void CircleWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(width() / 2, height() / 2);

for (int diameter = 0; diameter < 170; diameter += 6) {

int delta = abs((frameNo %120) - diameter / 2);
int alpha = 250 - (delta * delta) / 3 - diameter;
if (alpha > 0) {
painter.setPen(QPen(QColor(166, diameter / 2, 32, alpha), 5));

painter.drawEllipse(QRectF(-diameter / 2.0, -diameter / 2.0,
diameter, diameter));

}

}
}

ciclewidget.h:


#ifndef CIRCLEWIDGET_H
#define CIRCLEWIDGET_H

#include <QWidget>

class CircleWidget : public QWidget
{
Q_OBJECT

public:

CircleWidget(QWidget *parent = 0);
QSize minimumSizeHint() const;
QSize sizeHint() const;

public slots:
void nextAnimationFrame();

protected:
void paintEvent(QPaintEvent *event);

private:

int frameNo;
};

#endif

anda_skoa
17th June 2014, 09:19
You start the timer but the pause the main thread for 5 seconds.
You then stop the timer.

So the timer never ever has a chance to actually run.

QtWidgets is an event based UI framework, so you need to run an event loop to let it process events, such as paint requests, user input or timers.

the line


return app.exec();

does that.

What you could do is to use QTimer::singleShot() to delay the start of the second timer.

Cheers,
_

tissa
17th June 2014, 11:19
thx for you're response,
I used the QTimer::singleShot() but the animation didn't want to start !

Qt Code:

QObject::connect(timer, SIGNAL(timeout()), circl, SLOT(nextAnimationFrame()));
timer->start();
QTimer::singleShot(20,circle,SLOT(nextAnimationFra me()));

view.show();

wysota
17th June 2014, 11:44
Please show your current main().

tissa
17th June 2014, 14:06
#include <QApplication>

#include <QTimer>
#include<unistd.h>
#include<QGraphicsScene>
#include<QGraphicsProxyWidget>
#include<QGraphicsView>
#include "circlewidget.h"
#include<QTimeLine>


int main(int argc, char *argv[])
{

QApplication app(argc, argv);
CircleWidget * circle= new CircleWidget();
CircleWidget * circl= new CircleWidget();
QGraphicsScene scene;


QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget();
proxy->setWidget(circle);
proxy->setPos(0,1);

scene.addItem(proxy);
QTimer * time=new QTimer();
QTimer * timer=new QTimer();

QGraphicsProxyWidget *prox = new QGraphicsProxyWidget();
prox->setWidget(circl);
prox->setPos(200,100);
scene.addItem(prox);

/*QTimeLine *timer = new QTimeLine(5000);
timer->setFrameRange(0, 100);*/

QGraphicsView view(&scene);



QObject::connect(timer, SIGNAL(timeout()), circl, SLOT(nextAnimationFrame()));
timer->start();
QTimer::singleShot(200,circle,SLOT(nextAnimationFr ame()));

view.show();



return app.exec();

}

Added after 59 minutes:

My goal is to make animation with animated widget ( which are the concentric circle widget ) .....May I use the thread in this case ?!

anda_skoa
17th June 2014, 14:53
My suggestion was to use the single shot timer to start the second animation timer



QTimer::singleShot(5000, time, SLOT(start()));


You should probably also set some timer intervals.

Cheers,
_

wysota
17th June 2014, 15:30
What exactly is supposed to be animated? Your nextAnimationFrame() only increments some integer.

tissa
17th June 2014, 15:35
But it's animated u can test it if you want :3
thx anda_skoa :) you helped me ;)

wysota
17th June 2014, 16:08
You shouldn't animate it like that. Regardless if it works or not.

tissa
18th June 2014, 09:00
But how should I animate it?! :( ....they are circles....I want to do resizeable and smoothly animated circle. So I worked on the diametre to create a concentric circle .
It's not like that I should work ? you make me confused :(

wysota
18th June 2014, 10:35
But how should I animate it?! :( ....they are circles....I want to do resizeable and smoothly animated circle

So create property for the size of the circle and animate that property instead of some "frameNo" integer using some "nextAnimationFrame" function. If you set the diameter to "10" then it is supposed to be "10", if you set it to "16" then it should be "16". Right now you can only increase it by 1 in a rather unreliable manner.