вызов QGraphicsView::setViewport Qt с помощью специального QGLWidget
-
12-09-2019 - |
Вопрос
Раньше я получал от QGLWidget вот так:
class MyGLWidget : public QGLWidget
{
public:
// stuff...
virtual void initializeGL() { /* my custom OpenGL initialization routine */ }
// more stuff...
};
Однако я обнаружил, что если я попытаюсь инициализировать QGraphicsView с помощью моего пользовательского QGLWidget в качестве области просмотра, инициализацияGL не будет вызвана (устанавливая точку останова в библиотеке Qt, а также QGLWidget::initializeGL() при создании в обычном виде).
// 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)));
Где правильно разместить код, который в настоящее время находится в MyGLWidget::initializeGL()?
Решение 5
Я собираюсь пойти дальше и ответить на свой вопрос.Это не оптимально, но именно так я решил проблему.
Вместо
ui.graphicsView->setViewport(new MyGLWidget(QGLFormat(QGL::DoubleBuffer)));
Вместо этого у меня есть это:
ui.graphicsView->setViewport(new QGLWidget(new CustomContext(QGLFormat(QGL::SampleBuffers))));
CustomContext — это класс, производный от QGLContext.Я переопределил элемент создания, вот так:
virtual bool create(const QGLContext *shareContext = 0)
{
if(QGLContext::create(shareContext))
{
makeCurrent();
/* do my initialization here */
doneCurrent();
return true;
}
return false;
}
Я не думаю, что это оптимальный способ сделать это, но это лучше, чем альтернатива полному отсутствию определенного шага инициализации.Я все равно буду рад, если кто-нибудь оставит лучший ответ!
Другие советы
Слот setupViewport пользовательского QGraphicsView можно использовать для вызова updateGL() в QGLWidget, что приведет к вызову инициализацииGL().
class MyGraphicsView : public QGraphicsView
{
//... The usual stuff
protected slots:
virtual void setupViewport(QWidget *viewport)
{
QGLWidget *glWidget = qobject_cast<QGLWidget*>(viewport);
if (glWidget)
glWidget->updateGL();
}
};
Итак, я обнаружил, что QGraphicsView устанавливает собственный eventFilter в вашем окне просмотра QGLWidget, поэтому он никогда не видит события инициализации/изменения размера/перерисовки.Вероятно, это было сделано для правильной работы с drawBackground() и т. д.
На данный момент мое лучшее решение - перехватить желаемое событие либо в QGraphicsView::resizeEvent()/etc, либо установить собственный eventFilter в производном классе QGLWidget, чтобы перехватывать события изменения размера/рисования/и т. д. до того, как пользовательский eventFilter QGraphicsView проглотит их.
Боль, боль...интеграция виджетов, производных от QGlWidgets, в QGraphicsView — неинтересная часть Qt, насколько я знаю, это определенно одна из самых запутанных областей.В итоге я использовал часть кгллиб (из kde) под названием widgetproxy, который является очень достойной оболочкой QGlWidget.Я модифицировал его в соответствии со своими потребностями, но он работает достаточно хорошо для большинства общих случаев, когда вы хотите использовать существующий класс, полученный из QGlWidget, внутри QGraphicsView и рисовать поверх него другие объекты.
initializeGL()
не будет вызван до первого звонка либо paintGL()
или resizeGL()
а не при создании виджета.Это может произойти уже тогда, когда виджет впервые станет видимым.