【问题标题】:Using Qt's QTimer function to make animations in OpenGl在OpenGL中使用Qt的QTimer函数制作动画
【发布时间】:2013-05-11 16:53:46
【问题描述】:

在 OpenGl 中究竟如何使用 QTimer 来触发动画?

我想画一个简单的圆,每 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 中?

【问题讨论】:

    标签: c++ qt opengl animation


    【解决方案1】:

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

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

    哦,不要使用 int 作为圆的半径。如果您想要流畅的动画,请始终使用 float 或 double。

    【讨论】:

    • 谢谢,真的很有帮助!
    【解决方案2】:

    QPrivateSignal 不应成为连接调用中信号签名的一部分:

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

    QtCreator 的完成并没有理所当然地忽略它(有a bug report about that)。

    【讨论】:

      猜你喜欢
      • 2014-06-07
      • 1970-01-01
      • 2013-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      相关资源
      最近更新 更多