我试图在另一个帖子中绘制QOpenGLWidget
,这是我的代码:
// widget.h
class QGLCanvas;
class FrameRenderer: public QThread
{
Q_OBJECT
public:
FrameRenderer(QGLCanvas *parent);
void run() Q_DECL_OVERRIDE;
void stop();
void initialize();
void updateFrame(std::shared_ptr<cv::Mat> frame);
QGLCanvas *parent_;
std::atomic<bool> thread_run_;
bool initialize_;
GLuint texture_;
std::shared_ptr<cv::Mat> frame_;
QMutex mutex_;
};
class QGLCanvas : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
QGLCanvas(QWidget* parent = NULL);
virtual void initializeGL();
virtual void paintGL();
virtual void resizeGL(int width, int height);
void ShowImage(std::shared_ptr<cv::Mat> frame);
// for opengl rendering thread
FrameRenderer* render_thread_;
QTimer* render_timer_;
private slots:
void StartRendering();
};
//widget.cpp
#include "widget.h"
FrameRenderer::FrameRenderer(QGLCanvas* parent):
QThread(), parent_(parent)
{
thread_run_ = true;
initialize_ = false;
frame_ = std::make_shared<cv::Mat>();
cv::Mat img = cv::imread("./res/no_image.jpg");
*frame_ = img;
}
void FrameRenderer::stop()
{
thread_run_ = false;
}
void FrameRenderer::initialize()
{
if(initialize_)
return;
glGenTextures(1, &texture_);
glBindTexture(GL_TEXTURE_2D, texture_);
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, GL_RGB, frame_->cols,
frame_->rows, 0, GL_RGB, GL_UNSIGNED_BYTE,
NULL);
glBindTexture(GL_TEXTURE_2D, 0);
initialize_ = true;
}
void FrameRenderer::run()
{
while(true)
{
QMutexLocker lock(&mutex_);
if(!thread_run_)
break;
parent_->makeCurrent();
if(!initialize_)
initialize();
int width = parent_->width(), height = parent_->height();
glViewport(0, 0, width, height);
glClearColor(0, 0, 1, 1);
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture_);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame_->cols,
frame_->rows, GL_RGB, GL_UNSIGNED_BYTE,
frame_->data);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0, 0, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width, height, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0, height, 0.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
parent_->doneCurrent();
QMetaObject::invokeMethod(parent_, "update");
msleep(40);
}
}
void FrameRenderer::updateFrame(std::shared_ptr<cv::Mat> frame)
{
QMutexLocker lock(&mutex_);
frame_ = frame;
}
QGLCanvas::QGLCanvas(QWidget* parent)
: QOpenGLWidget(parent)
{
render_timer_ = new QTimer(this);
QObject::connect(render_timer_, SIGNAL(timeout()), this, SLOT(StartRendering()));
render_timer_->start(1000);
}
void QGLCanvas::initializeGL()
{
}
void QGLCanvas::resizeGL(int width, int height)
{
//stop QGLWidget standard behavior
}
void QGLCanvas::paintGL()
{
}
void QGLCanvas::StartRendering()
{
doneCurrent();
render_thread_ = new FrameRenderer(this);
context()->moveToThread(render_thread_);
render_thread_->start();
}
void QGLCanvas::ShowImage(std::shared_ptr<cv::Mat> frame)
{
if(render_thread_)
render_thread_->updateFrame(frame);
}
// main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// Check that the threaded OpenGL is supported.
if (!QOpenGLContext::supportsThreadedOpenGL())
{
std::cerr << "Threaded OpenGL is not supported" << std::endl;
return EXIT_FAILURE;
}
// Set the wanted surface format.
QSurfaceFormat format;
format.setDepthBufferSize(16);
format.setVersion(4, 4);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
// Calculate the position of the widget. The widget should be
// located so that the center is also at the center of desktop.
const QDesktopWidget* desktop = QApplication::desktop();
const QSize size(720, 576);
const QPoint position(
desktop->width() / 2 - size.width() / 2,
desktop->height() / 2 - size.height() / 2);
// Create the OpenGL widget
std::shared_ptr<QGLCanvas> widget = std::make_shared<QGLCanvas>();
widget->resize(size);
widget->move(position);
widget->show();
return app.exec();
}
问题是我收到了这个错误:
无法让QOpenglContext在另一个帖子中保持最新状态。
我使用QGLWidget
有类似的代码结构。但是当更改为QOpenGLWidget
时,它无法正常工作。