вызов QGraphicsView::setViewport Qt с помощью специального QGLWidget

StackOverflow https://stackoverflow.com/questions/1112167

Вопрос

Раньше я получал от 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() а не при создании виджета.Это может произойти уже тогда, когда виджет впервые станет видимым.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top