PDA

View Full Version : Painting over QOpenGLWidget in QGraphicsview clears viewport



KaBro
26th April 2016, 13:36
I'm making an application where I draw an image on a QGraphicsScene and then draw items over the scene in viewport coordinates (as I always want the items to appear in the same place, regardless of transformations of the scene).

In order to accomplish this I created the following subclass of QImageView:



class ImageView : public QGraphicsView
{
public:
ImageView(QWidget* parent = nullptr)
:QGraphicsView(parent)
{
}

protected:
void paintEvent(QPaintEvent* event)
{
QGraphicsView::paintEvent(event);
QPainter painter(viewport());
painter.setPen(QPen(Qt::green));
painter.drawRect(0, 0, 100, 100);
}
};


When using the standard viewport, this code works perfectly. However, when I set a QOpenQLWidget as viewport (using "myView->setViewport(new QOpenGLWidget());"), it will no longer paint
the image in the scene, only the green rectangle from the paintEvent. If I comment out the last 3 lines of the paintEvent, the image is drawn normally.

Through a bit of experimentation I learned that creating a QPainter with the QOpenGLWidget, will clear the widget.

As an alternative option I tried creating a class derived from QOpenGLWidget, overriding the paintGL() method (so that it paints the green rectangle) and then setting it as the viewport in a standard QGraphicsView. This didn't work either as the paintGL method is never called when the widget is used as a viewport.

So my questions are simple: Why doesn't the above code work with QOpenGLWidgets and how can I make it work?

To sum it up I need to do the following things:

Draw an image on a QGraphicsScene (or anywhere elsewhere I can zoom and translate at will).
Draw items over the image at a fixed place (so that they are always visible and not affected by zoom or translation).
It is important to note that the things I draw may not be known at compile time (in the actual application I draw a QPicture, which can contain anything).


The code example above is the smallest class I could create where I could recreate the problem, if you need more information please let me know.

d_stranz
26th April 2016, 22:17
Draw items over the image at a fixed place (so that they are always visible and not affected by zoom or translation).

Have a look at QGraphicsView::drawForeground(). I use a class derived from QGraphicsView where I actually have two scenes. One of them is the conventional scene that is drawn in the paint event, the other is a special scene that holds the overlay objects. This one is drawn in drawForeground() and can have a transformation matrix different from the other scene. (The widget is actually more complex than that - it also uses the drawBackground() method to draw a bitmap image which is then overlaid by the scene, which is then overlaid by the foreground scene).

KaBro
28th April 2016, 07:44
Thank you for your reply,

I replaced the paintEvent method in my class (see start of thread) with the following method:


void drawForeground(QPainter* painter, const QRectF& rect)
{
QGraphicsView::drawForeground(painter, rect);

painter->save();
painter->resetMatrix();
painter->resetTransform();
painter->setPen(QPen(Qt::green));
painter->drawRect(QRect(0, 0, 100, 100));
painter->restore();
}


It looks like this works exactly as I need it to (no problems with zooming or translations).