UI를, OpenGL의보기가 아닌, 정지, 또한 Qt는 5 사실이다. 파생되는 클래스를 QWidget
, 을 포함하여QGLWidget
등 다른 클래스로 옮기는 것은 오류입니다.
다른 스레드에서 렌더링하려면 QGLContext
(아니 QGLWidget
)을 렌더링 스레드로 이동해야합니다. 이 점에 관해서는 QGLWidget
의 문서를 따르십시오. 위젯의 페인트 이벤트 핸들러는 아무 것도하지 않아야합니다. 그렇지 않으면 틀린 (GUI) 스레드의 GL 컨텍스트가 사용되기 때문입니다. 사용자 지정 end
플래그의 필요성을 없애기 위해 렌더 스레드에서 실행중인 QObject
에서 0 지속 시간 타이머를 사용할 수 있습니다. QThread::quit()
을 호출하여 스레드의 이벤트 루프가 완료 될 때마다 개체 실행이 중지됩니다.
또한 안전하게 파괴 할 수있는 스레드 클래스를 사용해야합니다. 적절히 설계된 C++ 클래스는 언제나 파괴 가능합니다. QThread
은 별난 것입니다. 여기서 수정합니다.
스타일의 문제로, 위젯 자식을 힙에 할당 할 필요가 없습니다. 실제로 힙 블록은 QObject
인스턴스의 크기에 필적하는 오버 헤드를 가지고 있기 때문에 힙의 낭비는 거의 없습니다.
아래는 Qt에서 멀티 스레드 OpenGL을 위해 해결해야 할 사항에 대한 스케치입니다.
class Thread : public QThread {
using QThread::run; // final
public:
~QThread() { quit(); wait(); }
};
class ThreadGLWidget : public QGLWidget
{
void paintEvent(QPaintEvent *) {}
void resizeEvent(QResizeEvent *) { emit resized(size()); }
public:
explicit ThreadGLWidget(QWidget * parent = 0) : QGLWidget(parent) {
// Release the context in this thread.
doneCurrent();
}
Q_SIGNAL void resized(QSize);
};
class Animator : public QObject
{
Q_OBJECT
QBasicTimer mTimer;
QSize mWidgetSize;
QPointer<QGLContext> mGLContext;
void nextFrame() {
mGLContext.makeCurrent();
...
updateGL();
}
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() == mTimer.timerId()) nextFrame();
}
public:
explicit Animator(QGLContext * ctx, QObject * parent = 0) :
QObject(parent), mGLContext(ctx)
{
// The use of the timer obviates the custom stop flag. Our
// thread's event loop is not blocked and is quittable.
mTimer.start(0, this);
}
Q_SLOT void setSize(QSize size) { mWidgetSize = size; }
};
class Main_Widget : public QWidget
{
Q_OBJECT
public:
explicit Main_Widget(QWidget *parent = 0) : QWidget(parent),
mLayout(this), mStart("Start"), mStop("Stop"),
mAnimator(mOGL.context())
{
mLayout.addWidget(&mOGL, 0, 0, 1, 2);
mLayout.addWidget(&mOGL, 1, 0);
mLayout.addWidget(&mOGL, 1, 1);
mAnimator.setSize(mOGL.size());
mOGL.context()->moveToThread(&mThread);
mAnimator.moveToThread(&mThread);
mAnimator.connect(&mOGL, SIGNAL(resized(QSize)), SLOT(setSize(QSize)));
mThread.start();
}
private:
QGridLayout mLayout;
ThreadGLWidget mOGL;
QPushButton mStart;
QPushButton mStop;
Animator mAnimator; // must be declared before its thread and after the GL widget
QThread mThread;
// Destruction order of GL-related objects:
// 1. mThread - stops the animation, makes the animator and context threadless
// 2. mAnimator - now threadless, can be destructed from our thread
// 3. mOGL - its context is threadless and can be destructed from our thread
}
덩어리가 아닌 전체 코드를 표시하십시오. – lpapp
지금까지 문제가 무엇인지 분명합니다. +1 실제로 문제와 관련된 코드를 보여줍니다. –
@KubaOber : OP는 문제를 재현 할 수있는 자체 포함 된 예제를 보여줍니다. 품질 요구 사항은 결코 적지 않았으며, 절대로 그렇게되지 않을 것입니다. 엄밀히 말하자면, 모든 새로운 라인은 클래스 멤버가 아닌 다른 것을 위해 수행 될 수 있습니다. 모든 것을 [SSCCE] (http://sscce.org) 호환 테스트 케이스로 보는 것이 중요합니다. 대답은 추측 할 수 있지만 틀릴 수도 있습니다. – lpapp