How exactly do you use a QTimer to set off an animation in OpenGl?
I want to draw a simple circle and change the radius every 30 milliseconds, so it appears to grow and shrink smoothly.
Here's what I've come up with so far:
Header File
#include <QGLWidget>
#include <QTimer>
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit GLWidget(QWidget *parent = 0);
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
void timerEvent(QTimerEvent *event);
private:
QBasicTimer timer;
private slots:
void animate();
};
CPP File
int circRad = 0;
GLWidget::GLWidget(QWidget *parent) :
QGLWidget(parent)
{
QTimer *aTimer = new QTimer;
connect(aTimer,SIGNAL(timeout(QPrivateSignal)),SLOT(animate()));
aTimer->start(30);
}
void GLWidget::initializeGL()
{
glClearColor(1,1,1,0);
}
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0,0,1);
const float DEG2RAD = 3.14159/180;
glBegin(GL_LINE_LOOP);
for (int i=0; i <= 360; i++)
{
float degInRad = i*DEG2RAD;
glVertex2f(cos(degInRad)*circRad,sin(degInRad)*circRad);
}
glEnd();
}
void GLWidget::resizeGL(int width, int height)
{
glViewport(0,0,width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void GLWidget::animate()
{
if(circRad < 6)
{
circRad = circRad + 1;
}
else
{
circRad = circRad - 1;
}
update();
}
This(suprise, suprise) does nothing. Am I supposed to call a QTimerEvent? If so, does that mean I remove the animate SLOT and replace it with the QTimerEvent? Do I put the code from animate() into the QTimerEvent?
Typically you would only use a timer to trigger repaints, e.g. to limit the frame rate to 60 FPS. In the paint method, you would then check the current time, and do what you need to do to animate stuff. E.g. store the time t_start when the circle started growing, then offset the radius by sin(t - t_start).
By using the time (instead of the number of frames) you get animation that is independent of the frame rate. Keep in mind that Qt's timers are not exact. If you set a repeat interval of 30 ms, Qt doesn't guarantee that the slot is going to get called every 30 ms. Sometimes it might be 30 ms, sometimes 40 or even 100, depending on what else is in the event queue, or what's blocking the UI thread. If these hiccups occur, you don't want your animation to slow down.
Oh, and don't use int for the circle radius. If you want smooth animation, always use float or double.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With