Qt中的GLWidget仅在mousemove上更新

时间:2009-01-15 17:54:11

标签: user-interface qt opengl animation

我正在玩Qt试图建立一个小粒子系统。在那里,我已经将GLWidget子类化,并将其砍掉。一切进展顺利,直到我做了一些未知的改变,现在小部件只在我移动鼠标时重新绘制(由于QTimer我已经开火,它应该一直这样做)。相关代码:

OpenGLWidget.h

class OpenGLWidget :  public QGLWidget  {

   Q_OBJECT

public:
   OpenGLWidget(QWidget * parent = 0);
   ~OpenGLWidget();

public slots:
   void toggleEmitter();

protected:
   void initializeGL();
   void paintGL();
   void resizeGL(int width, int height);
   QSize minimumSizeHint() const;
   QSize sizeHint() const;
   void mousePressEvent(QMouseEvent *event);
   void mouseMoveEvent(QMouseEvent *event);

protected slots:
   void timeOut();

private:

   void testFunc(Particle & p, unsigned int t);

   QTime time;
   QTimer timer;

   Emitter emitter;

.cpp的相关代码

// in the constructor
time.start();
connect(&timer, SIGNAL(timeout()), this, SLOT(timeOut()));
timer.start(0);

void OpenGLWidget::initializeGL()  {
   GLuint tex = 0;

   qglClearColor(bgColor);
   glEnable(GL_DEPTH_TEST);   
   glClearDepth(1.0f);
    glDepthFunc(GL_LEQUAL);
   glShadeModel(GL_SMOOTH); 

   glDisable(GL_CULL_FACE);
   glEnable(GL_TEXTURE_2D); 
   glEnable( GL_BLEND );
   glBlendFunc( GL_SRC_ALPHA, GL_ONE); // _MINUS_SRC_ALPHA );

   glPointSize(3.0f);

   tex = bindTexture(QPixmap(QString("testparticle2.png")), GL_TEXTURE_2D);
   emitter = Emitter(Vector(0, 0, 0.0f), tex, 50, fastdelegate::FastDelegate2<Particle &, unsigned int>(this, &OpenGLWidget::testFunc));
}

void OpenGLWidget::paintGL()  {
   makeCurrent();
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   mainCam.SetView();

   glRotatef(xRot, 1, 0, 0);
   glRotatef(yRot, 0, 1, 0);

   emitter.Process(time.elapsed());

   totalTime += time.elapsed();
   time.restart();

}

void OpenGLWidget::resizeGL(int width, int height)  {
   contextWidth = width;
   contextHeight = height;

   glViewport(0, 0, width, height);

   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(55.0f, width / (float) height, 0.01f, 100.0f);

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();

}

void OpenGLWidget::timeOut()  {
   updateGL();
}

void OpenGLWidget::mousePressEvent(QMouseEvent *event)  {
    lastX = event->pos().x();
    lastY = event->pos().y();
}

void OpenGLWidget::mouseMoveEvent(QMouseEvent *event)  {
    int dx = event->x() - lastX;
    int dy = event->y() - lastY;

    if (event->buttons() & Qt::LeftButton) {
        xRot += 3 * dy;
        yRot += 3 * dx;
    } else if (event->buttons() & Qt::RightButton) {
        xRot += 3 * dy;
        yRot += 3 * dx;
    }

    lastX = event->pos().x();
    lastY = event->pos().y();

}

3 个答案:

答案 0 :(得分:1)

考虑到updateGL()调用调用paintGL()的glDraw(),你认为定时器应该调用与mousemove事件相同的功能。

你确定计时器实际上正在滴答作响吗?

顺便说一句,没有必要在paintGL()中调用makeCurrent()。

编辑:添加额外信息后:

QTimer says

  

“作为一个特例,一个QTimer用   所有的超时0次超时   窗口系统事件中的事件   队列已被处理。“

所以,如果你想让它尽可能快(尽管在Windows和大多数基于x386的系统上10ms可能是最小的),那么启动你的计时器的值为1而不是0.我假设这是问题是,只有当完成从队列中读取消息时它才会打勾。

答案 1 :(得分:1)

具有0秒超时的QTimer仅在事件循环获得控件时触发。我怀疑情况并非如此。但是,当您移动鼠标时,事件循环会再次处理某些事件,然后传递待处理的计时器事件。也许您需要在更新循环中调用processEvents()以确保来自QTimer的待处理计时器事件得到处理。

答案 2 :(得分:1)

定时器根本无法在不到20ms的时间内工作。它等于0。您可以使用简单的循环来测量从一次迭代到另一次迭代的时间。测量方法可能应该使用您的操作系统的API。