Chamando QGraphicsView :: setViewport do QT com um qglwidget personalizado
-
12-09-2019 - |
Pergunta
Já derivei do qglwidget antes, como assim:
class MyGLWidget : public QGLWidget
{
public:
// stuff...
virtual void initializeGL() { /* my custom OpenGL initialization routine */ }
// more stuff...
};
No entanto, acho que se eu tentar inicializar um QGraphicsView com meu qglWidget personalizado como a viewport, o InitializeGL não é chamado (definindo um ponto de interrupção na biblioteca QT, nem o QGLWidget :: InitializeGL () quando criado com planície).
// initializeGL, resizeGL, paintGL not called
ui.graphicsView->setViewport(new MyGLWidget(QGLFormat(QGL::DoubleBuffer)));
// initializeGL, resizeGL, paintGL *still* not called
ui.graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer)));
Onde está o local correto para colocar o código que atualmente reside no myglwidget :: InitializeGL ()?
Solução 5
Vou seguir em frente e responder minha própria pergunta. Isso não é ideal, mas foi assim que eu tive o problema.
Ao invés de
ui.graphicsView->setViewport(new MyGLWidget(QGLFormat(QGL::DoubleBuffer)));
Eu tenho isso em vez disso:
ui.graphicsView->setViewport(new QGLWidget(new CustomContext(QGLFormat(QGL::SampleBuffers))));
O CustomContext é uma classe que deriva do QGLContext. Eu substituí o membro Criar, como assim:
virtual bool create(const QGLContext *shareContext = 0)
{
if(QGLContext::create(shareContext))
{
makeCurrent();
/* do my initialization here */
doneCurrent();
return true;
}
return false;
}
Eu não acho que essa seja a maneira ideal de fazer isso, mas é melhor do que a alternativa de não ter uma etapa de inicialização específica. Eu ainda ficaria feliz por alguém deixar uma resposta melhor!
Outras dicas
O slot SetupViewPort de um qGraphicsView personalizado pode ser usado para ligar para o UpdateL () no QGLWidget, que fará com que o InitializeGL () seja chamado.
class MyGraphicsView : public QGraphicsView
{
//... The usual stuff
protected slots:
virtual void setupViewport(QWidget *viewport)
{
QGLWidget *glWidget = qobject_cast<QGLWidget*>(viewport);
if (glWidget)
glWidget->updateGL();
}
};
Então, o que eu encontrei é que o QGraphicsView instala um EventFilter personalizado na sua viewport QGLWidget, para que ele nunca veja os eventos inicialize/redimensione/repintar. Provavelmente, isso foi feito para fazê -lo funcionar corretamente com o Drawbackground () etc.
Minha melhor resolução atual é capturar o evento desejado no QGRAPHICSVIEW :: REDIMEVEVENT ()/etc ou instalar um EventFilter personalizado na sua classe derivada de QGLWidget para capturar os eventos redimensionados/tinta/etc antes que os eventos personalizados do QGRAPHICSVIEW os enxugem.
A dor, a dor, ... integrando os widgets derivados de qglWidgets no QGraphicsView não é divertido, das partes do QT que eu sei que essa é definitivamente uma das áreas mais confusas. Acabei usando uma parte de kgllib (fora de KDE) chamado widgetproxy que é um invólucro muito decente em torno de um qglwidget. Modifiquei -o para atender às minhas necessidades, mas funciona razoavelmente bem para os casos mais gerais em que você deseja usar uma classe existente derivada do QGLWidget dentro de uma View QGraphics e desenhar outras coisas sobre ela.
initializeGL()
não será chamado até a primeira chamada para paintGL()
ou resizeGL()
e não quando o widget é construído. Isso pode acontecer tão tarde quanto quando o widget é tornado visível pela primeira vez.