GLWidget в Qt обновляется только на mousemove - PullRequest
0 голосов
/ 15 января 2009

Я сейчас играю с 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 ]

1 голос
/ 29 мая 2009

QTimer с тайм-аутом 0 секунд срабатывает только тогда, когда цикл обработки получает управление. Я подозреваю, что это не тот случай. Однако при перемещении мыши цикл обработки событий (снова) обрабатывает некоторые события, а затем доставляет ожидающие события таймера. Возможно, вам нужно вызвать processEvents () в цикле обновления, чтобы убедиться, что обрабатывается ожидающее событие таймера из QTimer.

1 голос
/ 22 марта 2012

Таймер просто не может работать с менее чем 20 мс. Это равно 0 для этого. Вы можете использовать простой цикл с измерением времени от одной итерации к другой. Метод измерения, вероятно, должен использовать API вашей операционной системы.

1 голос
/ 15 января 2009

, учитывая, что updateGL () вызывает glDraw (), который вызывает paintGL (), можно подумать, что таймер должен вызывать ту же функциональность, что и событие mousemove.

Вы уверены, что таймер на самом деле тикает?

Кстати, нет необходимости вызывать makeCurrent () в paintGL () .

изменить: после добавления дополнительной информации:

QTimer говорит :

"Как особый случай, QTimer с тайм-аут 0 раз, как только все события в событии оконной системы очередь обработана. "

Итак, если вы хотите, чтобы он работал как можно быстрее (хотя 10 мс - это, вероятно, минимум для Windows и большинства систем на базе x386), тогда запустите таймер со значением 1 вместо 0. Я предполагаю, что проблема в том, что тикает только тогда, когда он завершил чтение сообщений из очереди.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...