Unsolved QOpenGLWidget not updating
-
Hi there!
I am having an issue with a QOpenGLWidget not always updating. I have several QOpenGLWidget's on the screen. One is controlled by a timer (i.e. a function is called every X seconds to do something then call update()). The other is updated every time a thread finishes rendering a point cloud. So there are at least 2 threads calling update on various QOpenGLWidget on the screen (though I don't believe there are multiple threads calling update on the SAME QOpenGLWidget). While this works 90% of the time every few minutes or so one of the QOpenGLWidgets will freeze. With print statements I can see that update is still being called on the widget and it is still accepting events (like mouse movement etc) but the display is not updated. If I resize the window it updates while I am actively resizing but not after. The only way I can get it to start working again is to switch to a different tab (both of the QOpenGLWidget's on the screen at any given time are inside QTabWidgets) and then switch back.Any ideas would be appreciated! I would post code but I have had difficulty making a sample program to replicate this given that the problem is so intermittent. I'm happy to post pieces that you think are relevant.
Thanks,
Matt -
@mlathrop qtimer part of code for first ,,,, than oly one qtglwidget code...
regards
giorgio -
Controller Code with the timer
void PreviewWindowController::set_content(ZoneContent* content) { if(worker_thread_) { worker_thread_->quit(); worker_thread_->wait(); delete worker_thread_; } content_ = content; worker_thread_ = new QThread(this); Worker w(preview_window_, content_); QTimer* timer = new QTimer(0); timer->setInterval((1000/framerate_)); timer->moveToThread(worker_thread_); w.moveToThread(worker_thread_); QObject::connect(worker_thread_, SIGNAL(started()), timer, SLOT(start())); QObject::connect(timer, SIGNAL(timeout()), SLOT(UpdateUiFromContent()), Qt::DirectConnection); worker_thread_->start(); } void PreviewWindowController::UpdateUiFromContent() { preview_window_->setImage(content_->get_preview_frame(preview_window_->width(), preview_window_->height())); }
QOpenGLWidget Code
void PreviewWindow::setImage(const QImage& image) { original_image_ = image; QImage letterbox = LetterboxImage(image, width(), height()); image_guard.lock(); img_ = letterbox; image_guard.unlock(); update(); } void PreviewWindow::paintGL() { QPainter p(this); //Set the painter to use a smooth scaling algorithm. p.setRenderHint(QPainter::SmoothPixmapTransform, 1); if(!img_.isNull()) { image_guard.lock(); p.drawImage(this->rect(), img_); image_guard.unlock(); } }
-
I use these only with little modification from qt4.8 up to qt5.8 ...... not the best, not well done, but it works ... maybe looking at it you will be able to bring you illumination ....
after these for sending image from qthread that grab the frame to gui windows (glwidget)I use connect/slot mechanism ... In m y gui there are 3 of these.glwidg::glwidg(QWidget *parent) : QGLWidget(parent) { this->setAttribute(Qt::WA_DeleteOnClose); //// inizialize capture dimension windows QGLWidget(QGLFormat(QGL::DirectRendering)); setMaximumSize(480,360);//(352,288); initializeGL(); //resizeGL(280,320); paintGL(); } int glwidg::xAtPress = 0; int glwidg::yAtPress = 0; int glwidg::xsend = 0; int glwidg::ysend = 0; cv::Point glwidg::SendMousePoint(0,0); void glwidg::mouseMoveEvent(QMouseEvent * event) { xAtPress = event->x(); yAtPress = event->y(); xsend = round(xAtPress*1.422222222); ysend = round(yAtPress*1.2); /* if (xsend < 0) {xsend = 0;} if (xsend > 640) {xsend = 640;} if (ysend < 0) {ysend = 0;} if (ysend > 480) {ysend = 480;}*/ SendMousePoint = cv::Point(xsend, ysend); emit MousePoint(SendMousePoint); //qDebug() << "Mausepoint glwidg: " << SendMousePoint.x << ", " << SendMousePoint.y; } void glwidg::resizeGL(int w, int h) { makeCurrent(); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, w, 0, h); // set origin to bottom left corner glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void glwidg::initializeGL() { makeCurrent(); glClearDepth(2000.0); glDisable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDisable(GL_COLOR_MATERIAL); glEnable(GL_BLEND); glEnable(GL_POLYGON_SMOOTH); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); qglClearColor(Qt::white); } void glwidg::paintGL() { makeCurrent(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); qglColor(Qt::white); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glMatrixMode(GL_MODELVIEW); /*+*/ glEnable(GL_DEPTH_TEST); if (cambio1 == 0) { qform1.load("/home/s/RIS/control2_106.png"); qq1frame = qform1.scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } else { qq1frame = qform1.scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } qqframe = qq1frame.mirrored(false, true); if(!qqframe.isNull()) { qqframe = qqframe.scaled(this->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); // glDrawPixels(qqframe.width(), qqframe.height(), GL_RGBA, GL_UNSIGNED_BYTE, qqframe.bits()); // or do 2D texture mapping glMatrixMode(GL_MODELVIEW); /**/ glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0,qqframe.width(),qqframe.height(),0); glMatrixMode(GL_MODELVIEW); //glDisable(GL_DEPTH_TEST); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D( GL_TEXTURE_2D, 0, 4, qqframe.width(), qqframe.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, qqframe.bits() ); glBegin(GL_QUADS); glTexCoord2f(0,0); glVertex2f(0,qqframe.height()); glTexCoord2f(0,1); glVertex2f(0,0); glTexCoord2f(1,1); glVertex2f(qqframe.width(),0); glTexCoord2f(1,0); glVertex2f(qqframe.width(),qqframe.height()); glEnd(); glDisable(GL_TEXTURE_2D); // .... end // qDebug() << ("ho disegnato??"); glDisable(GL_DEPTH_TEST); glFlush(); } if(qqframe.isNull()) { glClear(GL_COLOR_BUFFER_BIT); qglColor(Qt::white); } } void glwidg::donextcam() { makeCurrent(); } void glwidg::imma_orig_r1(QImage qi1) { cambio1 = 1; qform1 = qi1; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); updateGL(); } void glwidg::stopcam1(bool st1) { if (st1) { cambio1 = 0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); updateGL(); } else { cambio1 = 1; } }
regards
giorgio