使用定制的QGLWidget调用QGraphicsView: setViewport

时间:2022-09-10 18:27:16

I've derived from QGLWidget before, like so:

我之前从QGLWidget中推导过,比如:

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).

但是,我发现如果我尝试用我的自定义QGLWidget作为viewport初始化一个QGraphicsView, initializeGL不会被调用(在Qt库中设置一个断点,QGLWidget::initializeGL()创建的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()?

将当前驻留在MyGLWidget::initializeGL()中的代码放在哪里?

5 个解决方案

#1


4  

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

自定义QGraphicsView的setupViewport插槽可以用来调用QGLWidget上的updateGL(),这将导致调用initializeGL()。

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


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.

我发现QGraphicsView在QGLWidget viewport上安装一个自定义的eventFilter,这样它就不会看到initialize/resize/repaint事件。这样做可能是为了使它能够正确地使用drawBackground()等。

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.

我目前的最佳解决方案是在QGraphicsView: resizeEvent()/等中捕获所需的事件,或者在QGLWidget派生类上安装一个自定义的eventFilter,以便在QGraphicsView的自定义eventFilter吞噬事件之前捕获调整/绘制/等等事件。

#3


1  

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.

痛苦,痛苦,……将从QGlWidgets派生的小部件集成到QGraphicsView不是一件有趣的事情,在Qt中,我知道这肯定是比较混乱的领域之一。最后我使用了kgllib的一部分(来自kde) widgetproxy,这是一个非常好的QGlWidget包装器。我修改了它以适应我的需求,但是对于大多数一般情况下,您想要使用一个在QGraphicsView中从QGlWidget派生出来的存在类,并在它上面绘制其他的东西,这是很合理的。

#4


0  

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.

initializeGL()直到第一次调用paintGL()或resizeGL()时才会被调用,在构造小部件时也不会被调用。这可能会在小部件首次可见时发生。

#5


0  

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:

CustomContext是一个源自QGLContext的类。我重写了create成员,如下所示:

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!

我不认为这是最优的方法,但这比完全没有特定的初始化步骤要好。我还是很高兴有人能给我一个更好的答案!

#1


4  

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

自定义QGraphicsView的setupViewport插槽可以用来调用QGLWidget上的updateGL(),这将导致调用initializeGL()。

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


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.

我发现QGraphicsView在QGLWidget viewport上安装一个自定义的eventFilter,这样它就不会看到initialize/resize/repaint事件。这样做可能是为了使它能够正确地使用drawBackground()等。

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.

我目前的最佳解决方案是在QGraphicsView: resizeEvent()/等中捕获所需的事件,或者在QGLWidget派生类上安装一个自定义的eventFilter,以便在QGraphicsView的自定义eventFilter吞噬事件之前捕获调整/绘制/等等事件。

#3


1  

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.

痛苦,痛苦,……将从QGlWidgets派生的小部件集成到QGraphicsView不是一件有趣的事情,在Qt中,我知道这肯定是比较混乱的领域之一。最后我使用了kgllib的一部分(来自kde) widgetproxy,这是一个非常好的QGlWidget包装器。我修改了它以适应我的需求,但是对于大多数一般情况下,您想要使用一个在QGraphicsView中从QGlWidget派生出来的存在类,并在它上面绘制其他的东西,这是很合理的。

#4


0  

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.

initializeGL()直到第一次调用paintGL()或resizeGL()时才会被调用,在构造小部件时也不会被调用。这可能会在小部件首次可见时发生。

#5


0  

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:

CustomContext是一个源自QGLContext的类。我重写了create成员,如下所示:

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!

我不认为这是最优的方法,但这比完全没有特定的初始化步骤要好。我还是很高兴有人能给我一个更好的答案!