2013-05-11 24 views
3

您究竟如何使用QTimer在OpenGl中设置动画?使用Qt的QTimer函数在OpenGl中制作动画

我想绘制一个简单的圆圈并每30毫秒更改一次半径,因此它看起来平滑地增长和缩小。

下面是我想出迄今:

头文件

#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文件

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(); 
} 

这(惊喜,惊喜)什么都不做。我应该打电话给QTimerEvent?如果是这样,这是否意味着我删除了动画SLOT并将其替换为QTimerEvent?我将animate()中的代码放入QTimerEvent中吗?

回答

3

通常情况下,您只会使用计时器来触发重新绘制,例如,将帧速率限制为60 FPS。在绘画方法中,你会检查当前的时间,并做你需要做的东西动画的东西。例如。当圆圈开始增长时存储时间t_start,然后通过sin(t - t_start)偏移半径。

通过使用时间(而不是帧数),您可以获得独立于帧速率的动画。请记住,Qt的计时器并不准确。如果您设置30 ms的重复间隔,则Qt不保证每隔30 ms会调用一次该插槽。有时它可能是30毫秒,有时是40甚至100,这取决于事件队列中还有什么,或者什么阻塞了UI线程。如果发生这些打嗝,你不希望你的动画放慢速度。

呵呵,不要用int来表示圆的半径。如果您想要流畅的动画,请始终使用float或double。

+0

谢谢,这真的很有帮助! – JonAmen 2013-05-11 21:47:49

0

QPrivateSignal不应该在连接调用信号签名的一部分:

connect(aTimer,SIGNAL(timeout()),SLOT(animate())); 

QtCreator的完成不会忽略它尚未为它应该(有a bug report about that)。