我使用两个QGLWidgets。一个用于加载纹理,另一个用于渲染,但它不起作用。
我使用了来自http://blog.qt.digia.com/blog/2011/06/03/threaded-opengl-in-4-8/的以下解释
纹理上传线程上传许多(或大的)纹理通常是一个昂贵的操作,因为数据量被推送到GPU。同样,这是那些不必要地阻塞主线程的操作之一。在4.8中,您可以通过创建一对共享的QGLWidgets来解决这个问题。其中一个小部件在单独的线程中是当前的,但从未在屏幕上显示。主线程通知上传线程要上传哪些图像,上传线程只需对每个映像调用bindTexture(),然后在每个映像完成后通知主线程,以便将其绘制到屏幕上。
对于QT4.8和MinGW,它工作得很好,但是现在我在MSVC中使用QT5.1。当我想在线程当前设置小部件时,我得到了一个错误:
无法在其他线程中生成QOpenGLContext电流
我明白这个错误,但我怎样才能纠正它呢?当我不设置小部件当前时,我无法加载纹理(冻结在bindTexture()函数中)。我还想知道,为什么它适用于我的旧QT版本。当错误出现时,我可以按下“忽略错误”,程序无论如何都会加载纹理。
下面是一些示例代码:
加载纹理:
GLContext::GLContext(QWidget *parent, QGLWidget *myDisplayWidget) :
QGLWidget(parent,myDisplayWidget)
{
}..。
GLContext* myTextureWidget = new GLContext(this,myDisplayWidget);..。
void TextureLoadingThread::run()
{
makeCurrent(); //Here is the bug!
QImage *im = new QImage(filename);
GLuint textid = myTextureWidget->bindTexture(*im, GL_TEXTURE_2D, GL_RGBA);
}编辑:
当我将myTextureWidget的上下文移到线程上时,它会工作,但是当GUI构建时,我会从API中得到makeCurrent错误(QT5Widgetsd中的QLineEdit::setPlaceHolderText函数中的堆栈跟踪)。当我在显示主窗口几秒钟后将myTextureWidget移动到线程时,所有操作都很好。但是我怎么知道qt什么时候完成了GUI的构建呢?我将图形用户界面绘制到带有QGraphicsView视图的QGLWidget中。
myTextureWidget->context()->moveToThread(myTextureLoadingThread);发布于 2013-10-09 18:59:01
在启动新线程并调用makeCurrent()之前,必须先启动doneCurrent()。
void QGLWidget::startRendering()
{
doneCurrent();
context()->moveToThread(mTextureLoadingThread);
}然后打电话
void TextureLoadingThread::run()
{
makeCurrent(); //Here is the bug!
...
}这就是我为解决这个错误所做的工作。不幸的是,我没有完美的解决方案来使用线程来呈现。
//编辑
我上传了一个例子:example.zip
发布于 2014-12-02 05:50:24
现在可能为时已晚,但我也遇到了同样的问题,并找到了解决办法,所以下面是我所做的,希望它能帮助未来的程序员:
欧姆戈迪走在正确的轨道上。我认为仍然会出现相同的错误,因为主线程也在调用paintEvent(),这可能是为了使上下文当前。但是,第二个线程中已经存在相同的上下文,因此出现了错误。
因此,您基本上需要在第二个线程处于活动状态时,停止主线程试图在小部件中呈现。为此,我在QGLWidget中添加了一个布尔属性,并在创建第二个线程之前将其设置为true,并在完成线程时将其设置为false。然后,我修改了小部件的paintEvent(),使其仅在布尔值设置为false时才呈现。最后,我从第二个线程手动调用呈现函数。以下是一些代码:
//GLWidget derives from QGLWidget:
void GLWidget::paintEvent(QPaintEvent *e) {
if ( !_second_thread_active )
render();
}
//Then in your thread:
void Thread::doWork() {
//Do stuff
render();
}完成线程后,不要忘记将上下文从第二个线程发送回主线程!
doneCurrent();
context()->moveToThread(&qapp->thread());HTH
https://stackoverflow.com/questions/19202338
复制相似问题