calling Qt's QGraphicsView::setViewport with a custom QGLWidget

做~自己de王妃 提交于 2019-12-07 08:35:44

问题


I've derived from QGLWidget before, like so:

class MyGLWidget : public QGLWidget
{
public:
   // stuff...

   virtual void initializeGL() { /* my custom OpenGL initialization routine */ }

   // more stuff...
};

However, I find that if I try to initialize a QGraphicsView with my custom QGLWidget as the viewport, initializeGL doesn't get called (setting a breakpoint within the Qt library, neither does QGLWidget::initializeGL() when created plain).

// 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)));

Where is the correct location to place the code that currently resides in MyGLWidget::initializeGL()?


回答1:


The setupViewport slot of a custom QGraphicsView could be used to call updateGL() on the QGLWidget, which will cause initializeGL() to be called.

class MyGraphicsView : public QGraphicsView
{
    //... The usual stuff

protected slots:
    virtual void setupViewport(QWidget *viewport)
    {
        QGLWidget *glWidget = qobject_cast<QGLWidget*>(viewport);
        if (glWidget)
            glWidget->updateGL();
    }

};



回答2:


So what I've found is QGraphicsView installs a custom eventFilter on your QGLWidget viewport so it never sees the initialize/resize/repaint events. This probably was done to make it work properly with drawBackground() etc.

My current best resolution is to catch the desired event either in QGraphicsView::resizeEvent()/etc, or install a custom eventFilter on your QGLWidget derived class to catch the resize/paint/etc events before QGraphicsView's custom eventFilter swallows them.




回答3:


The pain, the pain, ... integrating widgets derived from QGlWidgets into QGraphicsView is no fun, of the parts of Qt that I know this is definitely one of the messier areas. I ended up using a part of kgllib (out of kde) called widgetproxy that is a very decent wrapper around a QGlWidget. I modified it to fit my needs but works reasonably well for most general cases where you want to use an exisiting class derived from QGlWidget inside a QGraphicsView and draw other things on top of it.




回答4:


initializeGL() won't get called until the first call to either paintGL() or resizeGL() and not when the widget is constructed. This may happen as late as when the widget is first made visible.




回答5:


I'm going to go ahead and answer my own question. This isn't optimal, but this is how I've gotten around the problem.

Instead of

ui.graphicsView->setViewport(new MyGLWidget(QGLFormat(QGL::DoubleBuffer)));

I've got this instead:

ui.graphicsView->setViewport(new QGLWidget(new CustomContext(QGLFormat(QGL::SampleBuffers))));

CustomContext is a class that derives from QGLContext. I've overridden the create member, like so:

virtual bool create(const QGLContext *shareContext = 0)
{
    if(QGLContext::create(shareContext))
    {
        makeCurrent();

        /* do my initialization here */

        doneCurrent();

        return true;
    }

    return false;
}

I don't think this is the optimal way to do this, but it's better than the alternative of not having a specific initialization step at all. I'd still be happy to have someone leave a better answer!



来源:https://stackoverflow.com/questions/1112167/calling-qts-qgraphicsviewsetviewport-with-a-custom-qglwidget

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!