2013-08-20 12 views
7

Ich mache eine Menge Textur-Upload (60 VGA-Bilder pro Sekunde) und es blockiert meinen UI-Thread. Von the Qt 5.1 QGLWidget manual page (Hervorhebung von mir):QGLWidget in einem anderen Thread? Worauf bezieht sich die Dokumentation?

Textur hochladen in einem Thread. Das Hochladen von Texturen in einem Thread ist möglicherweise sehr nützlich für Anwendungen, die große Mengen von Bildern verarbeiten, die angezeigt werden müssen, wie beispielsweise eine Fotogalerieanwendung. Dies wird in Qt durch die vorhandene bindTexture() API unterstützt. Eine einfache Möglichkeit besteht darin, zwei freigegebene QGLWidgets zu erstellen. Einer wird im Haupt-GUI-Thread aktuell gemacht, während der andere im Textur-Upload-Thread aktuell gemacht wird. Das Widget im Upload-Thread wird nie angezeigt, es wird nur zum Teilen von Texturen mit dem Haupt-Thread verwendet. Informieren Sie den Hauptthread für jede Textur, die über bindTexture() gebunden ist, damit er die Textur verwenden kann.

Was? Wie kann eine QWidget-basierte Klasse wie ein QGLWidget in einen Thread verschoben werden? Der Versuch, dies zu tun, führt zu:

QObject::moveToThread: Widgets cannot be moved to a new thread 

Ich verstehe nicht, was die Dokumentation schlägt ich implementieren, um z. bindTexture() Ausführung aus dem UI-Thread.

Dies auch hier erwähnt wird: Qt4/Opengl bindTexture in separated thread

kein Code geschrieben, obwohl es.

Antwort

3

Ich muss sagen, ich erinnere mich nicht genau, wie ich das gemacht habe, jedenfalls denke ich nicht, dass das QGLWidget in einen anderen Thread verschoben werden muss, und das ist tatsächlich nicht das, was die Dokumentation sagt. Es sagt, um es aktuell zu machen: QGLWidget::makeCurrent(). Das wird den OpenGL-Kontext dieses QGLWidget in dem neuen Thread aktuell machen.

Allerdings würde ich mit einer QGLContext Klasse versuchen. Sie können einen QGLContext instanziieren und dann QGLContext :: create() aufrufen, um ihn mit demjenigen von QGLWidget zu teilen. Mit dem QGLContext können Sie die Texturen binden.

+0

Yep. Weitere Informationen [hier] (http://blog.qt.digia.com/blog/2011/06/03/threaded-opengl-in-4-8/). In Qt 5 sollten Sie QOpenGL * -Klassen und nicht QGL * -Klassen verwenden, wo dies möglich ist. – peppe

6

Etwas spät auf die Antwort, aber Widgets müssen durch den Thread, der sie erstellt hat, in einen neuen Thread verschoben werden. In Ihrem Fall so etwas wie:

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

glWidget->doneCurrent(); 
glWidget->context()->moveToThread(newThread); 

hier nur ich den openGL Zusammenhang mit dem neuen Thread bewegen, erfordert dies, dass einige Überschreibungen in QGLWidget gefangen werden und ignorieren. Sie müssen eine neue abgeleitete Klasse aus QGLWidget erstellen und das Folgende überschreiben.

Dies verhindert, dass der Standard-UI-Thread versucht, den OpenGL-Kontext im UI-Thread aktuell zu machen. Sobald Sie das oben genannte überschreiben, benötigen Sie ein Ereignissystem, um den Thread zu benachrichtigen, dass einige der Ereignisse passiert sind, hauptsächlich resizeGl und paintGL, ansonsten reagiert das Widget nicht richtig auf andere um es herum.

Der letzte Teil ist in der Erstellung des QGLWidget. Einer der Parameter in dem Konstrukt ist 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) 

Sie würden dann die ui QGLWidget erstellen und die Gewinde GLWidget (derivided von QGLWidget mit all den Überschreibungen oben erwähnt) dafür, dass, wenn der Faden GLWidget Schaffung Sie stellen das QGLWidget als sharedWidget bereit.Dadurch werden die 2 OpenGL-Kontexte geteilt und Sie können eine Textur in eine Datei laden, die beide sehen können. Der Code sollte wie folgt aussehen:

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

threadedWidget->moveToThread(newThread); 

Was Code vor kurzem ich ein kleines Beispiel-Programm mit Gewinde QGLWidgets hauptsächlich für openGL/OpenCL Interop geschrieben, aber es zeigt muliple QGLWidgets in Ziehfäden mit einem einzigen Kontext zu teilen. Der Code ist auf github und eine Beschreibung ist hier http://www.krazer.com/?p=109

+0

Link-only-Antworten werden abgeraten. Ihre Antwort wird ungültig, wenn eine der verknüpften Ressourcen verschoben oder entfernt wird. Eine Antwort sollte mindestens die Hauptpunkte enthalten, auch wenn hinter einem Link mehr Inhalt steht. –

+0

+1. Links sind nicht erwünscht, aber das ist eine sehr gute Antwort und ich würde Sie gerne als Teil unserer Community sehen. – Mikhail

Verwandte Themen