QGLWidget在另一个线程?什么是文件?

nja*_*nke 7 opengl qt multithreading qt5

我正在做很多纹理上传(每秒60个VGA图像),它阻止了我的UI线程.从Qt 5.1 QGLWidget手册页(强调我的):

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

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

QObject::moveToThread: Widgets cannot be moved to a new thread
Run Code Online (Sandbox Code Playgroud)

我不明白文档建议我实现什么,以便将例如bindTexture()执行移出UI线程.

这里也提到了:Qt4/Opengl bindTexture在分离的线程中

虽然没有张贴代码.

Kra*_*zer 8

答案的后期不多,但是小部件需要通过创建它们的线程移动到新线程.在你的情况下像:

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

glWidget->doneCurrent();
glWidget->context()->moveToThread(newThread);
Run Code Online (Sandbox Code Playgroud)

这里我只将openGL上下文移动到新线程,这要求捕获并忽略QGLWidget中的一些覆盖.您需要从QGLWidget创建一个新的派生类并覆盖以下内容.

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

virtual void initializeGL();
virtual void resizeGL(int width, int height);
virtual void paintGL();
Run Code Online (Sandbox Code Playgroud)

这会阻止标准UI线程尝试在UI线程中使OpenGL上下文变为当前.一旦你覆盖了上面的内容,你将需要一个事件系统来通知线程发生了一些事件,主要是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 )
Run Code Online (Sandbox Code Playgroud)

然后,您可以创建创建GLWidget您提供QGLWidget来绘图作为sharedWidget线程时确保用户界面QGLWidget来绘图和螺纹GLWidget(从QGLWidget来绘图derivided与上面提到的所有覆盖的).这将使2 opengl上下文共享,并允许您加载纹理,两者都可以看到.代码看起来应该是这样的:

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

threadedWidget->moveToThread(newThread);
Run Code Online (Sandbox Code Playgroud)

至于代码,我最近使用主要用于openGL/openCL互操作的线程QGLWidgets编写了一个小示例程序,但它显示了在共享单个上下文的绘制线程中使用多个QGLWidgets.代码在github上,描述在http://www.krazer.com/?p=109


Luc*_*lon 3

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

但是,我会尝试使用QGLContext类。您可以实例化一个 QGLContext,然后调用 QGLContext::create() 与 QGLWidget 之一共享。使用 QGLContext 您可以绑定纹理。