Multithreading QGLWidget在另一个线程中?文件所指的是什么?

Multithreading QGLWidget在另一个线程中?文件所指的是什么?,multithreading,qt,opengl,qt5,Multithreading,Qt,Opengl,Qt5,我正在进行大量纹理上传(每秒60个VGA图像),这会阻塞我的UI线程。来自(我的): 纹理上传在线程中。 在线程中执行纹理上载对于处理大量需要显示的图像的应用程序可能非常有用,例如照片库应用程序。Qt通过现有的bindTexture()API支持这一点。一个简单的方法是创建两个共享QGLWidget。一个在主GUI线程中变为当前,而另一个在纹理上载线程中变为当前。上传线程中的小部件从未显示,它仅用于与主线程共享纹理。对于通过bindTexture()绑定的每个纹理,通知主线程,以便它可以开始使用

我正在进行大量纹理上传(每秒60个VGA图像),这会阻塞我的UI线程。来自(我的):

纹理上传在线程中。 在线程中执行纹理上载对于处理大量需要显示的图像的应用程序可能非常有用,例如照片库应用程序。Qt通过现有的bindTexture()API支持这一点。一个简单的方法是创建两个共享QGLWidget。一个在主GUI线程中变为当前,而另一个在纹理上载线程中变为当前。上传线程中的小部件从未显示,它仅用于与主线程共享纹理。对于通过bindTexture()绑定的每个纹理,通知主线程,以便它可以开始使用该纹理

什么?如何将基于QWidget的类(如QGLWidget)移动到线程?尝试这样做会导致:

QObject::moveToThread: Widgets cannot be moved to a new thread
我不明白文档建议我实现什么,以便将例如
bindTexture()
的执行移出UI线程

这里也提到了这一点:


不过,那里没有发布代码。

我不得不说,我不记得我是如何做到这一点的,无论如何,我不认为QGLWidget必须移动到另一个线程,事实上,文档中并没有这么说。它说让它成为当前的:()。这将使QGLWidget的OpenGL上下文在新线程中处于当前状态


然而,我会尝试一门课。您可以实例化一个QGLContext,然后调用QGLContext::create()来和QGLWidget之一共享。通过QGLContext,您可以绑定纹理。

回答得有点晚,但小部件需要通过创建它们的线程移动到新线程。在您的情况下,类似于:

QGLWidget *glWidget=new QGLWidget();
QThread *newThread=new QThread();

glWidget->doneCurrent();
glWidget->context()->moveToThread(newThread);
这里我只将openGL上下文移动到新线程,这需要捕获并忽略QGLWidget中的一些覆盖。您需要从QGLWidget创建一个新的派生类,并覆盖以下内容

virtual void glInit();
virtual void glDraw();

virtual void initializeGL();
virtual void resizeGL(int width, int height);
virtual void paintGL();
这将阻止标准UI线程尝试使OpenGL上下文成为UI线程中的当前上下文。一旦覆盖了上述内容,您将需要一个事件系统来通知线程某些事件已经发生,主要是resizeGl和paintGL,否则小部件将无法与周围的其他小部件正确反应

最后一部分是QGLWidget的创建。构造中的一个参数是const QGLWidget*shareWidget:

QGLWidget ( QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WindowFlags f = 0 )
QGLWidget ( QGLContext * context, QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WindowFlags f = 0 )
QGLWidget ( const QGLFormat & format, QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WindowFlags f = 0 )
然后,您将创建ui QGLWidget和线程GLWidget(从QGLWidget派生,具有上述所有覆盖),确保在创建线程GLWidget时,您将QGLWidget作为共享Widget提供。这将使2个opengl contexted共享,并允许您加载一个双方都能看到的纹理。代码应该如下所示:

QGLWidget *glWidget=new QGLWidget();
GLWidget *threadedWidget=new GLWidget(0/*parent*/, glWidget);
QThread *newThread=new QThread();

threadedWidget->moveToThread(newThread);

至于代码,我最近编写了一个使用线程QGLWidgets的小示例程序,主要用于openGL/openCL互操作,但它显示了在共享单个上下文的绘制线程中使用多个QGLWidgets。代码已打开,此处有说明

Yep。更多信息。此外,在Qt5中,如果可能的话,实际上应该使用QOpenGL*类,而不是QGL*类。不建议使用仅链接的答案。如果移动或删除任何链接资源,您的答案将无效。答案应该至少包含要点,即使链接后面有更多内容。+1。不鼓励链接,但这是一个非常好的回应,我真的希望看到你成为我们社区的一部分。