2013-05-11 32 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)。