3

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 に入れますか?

4

2 に答える 2

3

通常は、フレーム レートを 60 FPS に制限するなど、再描画をトリガーするためだけにタイマーを使用します。ペイント メソッドでは、現在の時間を確認し、アニメーション化するために必要なことを行います。たとえば、円が成長し始めた時間を保存しt_start、半径を でオフセットしsin(t - t_start)ます。

(フレーム数の代わりに) 時間を使用すると、フレーム レートに依存しないアニメーションが得られます。Qt のタイマーは正確ではないことに注意してください。30 ミリ秒の繰り返し間隔を設定した場合、Qt はスロットが 30 ミリ秒ごとに呼び出されることを保証しません。イベント キューに他に何があるか、または UI スレッドをブロックしているものに応じて、30 ミリ秒、40 ミリ秒、または 100 ミリ秒になることもあります。これらの問題が発生した場合、アニメーションの速度が低下することは望ましくありません。

ああ、円の半径に int を使用しないでください。スムーズなアニメーションが必要な場合は、常に float または double を使用してください。

于 2013-05-11T17:24:09.387 に答える