Accelerate QGraphicsView with openGL widget - correct up to date workflow?
-
@kenchan
Hey, just to add to what i just said...There is another way to accelerate drawing stuff in a QGraphicsView. If you derive your own class and implement the drawBackground() and drawForeground() functions.
You still need to use the beginNativePainting() and endNativePainting() functions and separate OpenGL call from normal Painter calls.
I use this technique to draw grids and other stuff using OpenGL. Notice I am saving and restoring the painter state, this is important.
Something like this...void MyGraphicsView::drawBackground(QPainter * painter, const QRectF & rect) { if(painter->paintEngine()->type() == QPaintEngine::OpenGL2) <<< or whatever OpenGL spec is good for you { painter->save(); painter->beginNativePainting(); ... do your super OPenGL stuff here ... painter->endNativePainting(); painter->restore(); } else { QGraphicsView::drawBackground(painter,rect); } } -
@kenchan said in Accelerate QGraphicsView with openGL widget - correct up to date workflow?:
Interesting thanks! I just added a one file example above your post. Looks like we posted at the same time :- )))
-
@Dariusz
Sure , no problem. I just made a few edits to my last post to clean it up a bit.
Good luck with your OpenGL stuff.@kenchan
Thanks, saw it, sadly still no luck, the app still has issues even when I use the painter save/restore with begin paintings. The stylesheet break it all and I have no idea how to remove it from the widget but still have control over background & text fonts in graphicsview/scene :/ I guess for scene I could just draw a QRect the size of viewport but to control font color... not sure... hmm joy :- )Will post if I have any luck with it.
-
@kenchan said in Accelerate QGraphicsView with openGL widget - correct up to date workflow?:
Interesting thanks! I just added a one file example above your post. Looks like we posted at the same time :- )))
-
@kenchan
Thanks, saw it, sadly still no luck, the app still has issues even when I use the painter save/restore with begin paintings. The stylesheet break it all and I have no idea how to remove it from the widget but still have control over background & text fonts in graphicsview/scene :/ I guess for scene I could just draw a QRect the size of viewport but to control font color... not sure... hmm joy :- )Will post if I have any luck with it.
-
@Dariusz
So what are you styling in your stylesheet?
EDIT. Ah i see it in the main function, is that all you are doing with styling?@kenchan I use mostly use this https://github.com/ColinDuquesnoy/QDarkStyleSheet and then I adjust it & push it further to get it to look nice. But for this example I posted above I just made a simple test to show the error.
Right now I'm trying to figure out how I can paint a rect the size of my visible viewport but that is producting some... "interesting" results. Have a look -> replace this function to see it has some interesting issues :- )
void gView::drawBackground(QPainter *painter, const QRectF &rect) { if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) { painter->save(); painter->beginNativePainting(); //... //do your super OPenGL stuff here // ... const int gridSize = 20; qreal left = int(rect.left()) - (int(rect.left()) % gridSize); qreal top = int(rect.top()) - (int(rect.top()) % gridSize); QVarLengthArray<QLineF, 100> lines; for (qreal x = left; x < rect.right(); x += gridSize) lines.append(QLineF(x, rect.top(), x, rect.bottom())); for (qreal y = top; y < rect.bottom(); y += gridSize) lines.append(QLineF(rect.left(), y, rect.right(), y)); //QPen penHLines(QColor(75, 75, 75), 1, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin); //painter->setPen(penHLines); //painter->drawLines(lines.data(), lines.size()); QRectF rec(viewport()->rect()); rec.setTopLeft({0 - rec.width() / 2, 0 - rec.height() / 2}); QBrush b(QColor(75, 15, 34, 255)); painter->setBrush(b); painter->setPen(QPen()); painter->drawRect(rec); painter->endNativePainting(); painter->restore(); } else { QGraphicsView::drawBackground(painter, rect); } }``` -
@kenchan I use mostly use this https://github.com/ColinDuquesnoy/QDarkStyleSheet and then I adjust it & push it further to get it to look nice. But for this example I posted above I just made a simple test to show the error.
Right now I'm trying to figure out how I can paint a rect the size of my visible viewport but that is producting some... "interesting" results. Have a look -> replace this function to see it has some interesting issues :- )
void gView::drawBackground(QPainter *painter, const QRectF &rect) { if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) { painter->save(); painter->beginNativePainting(); //... //do your super OPenGL stuff here // ... const int gridSize = 20; qreal left = int(rect.left()) - (int(rect.left()) % gridSize); qreal top = int(rect.top()) - (int(rect.top()) % gridSize); QVarLengthArray<QLineF, 100> lines; for (qreal x = left; x < rect.right(); x += gridSize) lines.append(QLineF(x, rect.top(), x, rect.bottom())); for (qreal y = top; y < rect.bottom(); y += gridSize) lines.append(QLineF(rect.left(), y, rect.right(), y)); //QPen penHLines(QColor(75, 75, 75), 1, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin); //painter->setPen(penHLines); //painter->drawLines(lines.data(), lines.size()); QRectF rec(viewport()->rect()); rec.setTopLeft({0 - rec.width() / 2, 0 - rec.height() / 2}); QBrush b(QColor(75, 15, 34, 255)); painter->setBrush(b); painter->setPen(QPen()); painter->drawRect(rec); painter->endNativePainting(); painter->restore(); } else { QGraphicsView::drawBackground(painter, rect); } }```Ok this appear to be somewhat working... I wonder how pricey it is comparing to a proper "workflow" of achieving this ?
void gView::drawBackground(QPainter *painter, const QRectF &rect) { if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) { painter->save(); painter->beginNativePainting(); const int gridSize = 20; qreal left = int(rect.left()) - (int(rect.left()) % gridSize); qreal top = int(rect.top()) - (int(rect.top()) % gridSize); QVarLengthArray<QLineF, 100> lines; for (qreal x = left; x < rect.right(); x += gridSize) lines.append(QLineF(x, rect.top(), x, rect.bottom())); for (qreal y = top; y < rect.bottom(); y += gridSize) lines.append(QLineF(rect.left(), y, rect.right(), y)); QRectF rec(-2000,-2000,4000,4000); QBrush b(QColor(75, 15, 34, 255)); QPen myPen(Qt::NoPen); painter->setBrush(b); painter->setPen(myPen); painter->drawRect(rec); QPen penHLines(QColor(75, 75, 75), 1, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin); painter->setPen(penHLines); painter->drawLines(lines.data(), lines.size()); painter->endNativePainting(); painter->restore(); } else { QGraphicsView::drawBackground(painter, rect); } }EDIT. Ok so Instead of doing in in view, I decided to do it in scene, this way every view will pick the same "look", as well as I can just use rect and just fill it...
void gScene::drawBackground(QPainter *painter, const QRectF &rect) { if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) { painter->save(); painter->beginNativePainting(); const int gridSize = 20; qreal left = int(rect.left()) - (int(rect.left()) % gridSize); qreal top = int(rect.top()) - (int(rect.top()) % gridSize); QVarLengthArray<QLineF, 100> lines; for (qreal x = left; x < rect.right(); x += gridSize) lines.append(QLineF(x, rect.top(), x, rect.bottom())); for (qreal y = top; y < rect.bottom(); y += gridSize) lines.append(QLineF(rect.left(), y, rect.right(), y)); QBrush b(QColor(75, 15, 34, 255)); QPen myPen(Qt::NoPen); painter->setBrush(b); painter->setPen(myPen); painter->drawRect(rect); QPen penHLines(QColor(75, 75, 75), 1, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin); painter->setPen(penHLines); painter->drawLines(lines.data(), lines.size()); painter->endNativePainting(); painter->restore(); } else { QGraphicsScene::drawBackground(painter, rect); } }This also mean that I don't have to subclass qOpenGLWidget, and I can just use it natively + setFormat on it to get AA to work.
-
Ok this appear to be somewhat working... I wonder how pricey it is comparing to a proper "workflow" of achieving this ?
void gView::drawBackground(QPainter *painter, const QRectF &rect) { if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) { painter->save(); painter->beginNativePainting(); const int gridSize = 20; qreal left = int(rect.left()) - (int(rect.left()) % gridSize); qreal top = int(rect.top()) - (int(rect.top()) % gridSize); QVarLengthArray<QLineF, 100> lines; for (qreal x = left; x < rect.right(); x += gridSize) lines.append(QLineF(x, rect.top(), x, rect.bottom())); for (qreal y = top; y < rect.bottom(); y += gridSize) lines.append(QLineF(rect.left(), y, rect.right(), y)); QRectF rec(-2000,-2000,4000,4000); QBrush b(QColor(75, 15, 34, 255)); QPen myPen(Qt::NoPen); painter->setBrush(b); painter->setPen(myPen); painter->drawRect(rec); QPen penHLines(QColor(75, 75, 75), 1, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin); painter->setPen(penHLines); painter->drawLines(lines.data(), lines.size()); painter->endNativePainting(); painter->restore(); } else { QGraphicsView::drawBackground(painter, rect); } }EDIT. Ok so Instead of doing in in view, I decided to do it in scene, this way every view will pick the same "look", as well as I can just use rect and just fill it...
void gScene::drawBackground(QPainter *painter, const QRectF &rect) { if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) { painter->save(); painter->beginNativePainting(); const int gridSize = 20; qreal left = int(rect.left()) - (int(rect.left()) % gridSize); qreal top = int(rect.top()) - (int(rect.top()) % gridSize); QVarLengthArray<QLineF, 100> lines; for (qreal x = left; x < rect.right(); x += gridSize) lines.append(QLineF(x, rect.top(), x, rect.bottom())); for (qreal y = top; y < rect.bottom(); y += gridSize) lines.append(QLineF(rect.left(), y, rect.right(), y)); QBrush b(QColor(75, 15, 34, 255)); QPen myPen(Qt::NoPen); painter->setBrush(b); painter->setPen(myPen); painter->drawRect(rect); QPen penHLines(QColor(75, 75, 75), 1, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin); painter->setPen(penHLines); painter->drawLines(lines.data(), lines.size()); painter->endNativePainting(); painter->restore(); } else { QGraphicsScene::drawBackground(painter, rect); } }This also mean that I don't have to subclass qOpenGLWidget, and I can just use it natively + setFormat on it to get AA to work.
Yes i have it doing the same thing now.
The thing is, the startNativePainting() endNativePainting() things are supposed to be where you put raw OpenGL calls and such. You don't need them if you use the painter calls and you probably don't need to save the painter state unless it messes up what you want to do.
Just using a QOpenGLWidget as the viewport widget enables OpenGL acceleration for the painter, or at least that is what the Doc says here. -
Yes i have it doing the same thing now.
The thing is, the startNativePainting() endNativePainting() things are supposed to be where you put raw OpenGL calls and such. You don't need them if you use the painter calls and you probably don't need to save the painter state unless it messes up what you want to do.
Just using a QOpenGLWidget as the viewport widget enables OpenGL acceleration for the painter, or at least that is what the Doc says here. -
@kenchan
Interesting thanks!Well I got it solved with code above, so I'll mark the topic as solved. Thanks so much for your time & help!