c++qtopenglqgraphicsviewqglwidget

Using a QGLWidget as the viewport for QGraphicsView results in black screen


I have a QGraphicsView displaying a QGraphicsScene which I would like to use a QGLWidget as the viewport for. The Qt documentation leads me to believe that it is a simple as giving my QGraphicsScene a QGLWidget as a viewport, however I get a black screen when I try.

#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QGLWidget>

class View : public QGraphicsView
{
  Q_OBJECT
public:
  explicit View(QWidget *parent = 0) :
    QGraphicsView(parent)
  {
    QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem(QPixmap(":/images/chart.png"));

    QGraphicsScene *scene = new QGraphicsScene();
    scene->addItem(pixmapItem);
    setScene(scene);

    setViewport(new QGLWidget());
  }
};

If I comment the last to lines pertaining to the QGLWidget then my pixmap displays fine, however with them in I only see a black screen. I have also noticed that the CPU usage is significantly higher when the QGLWidget is in. I have successfully used QGLWidgets in the past (never with a QGraphicsView though) so I think that OpenGL itself is working correctly. I have tried changed the gl clear color to try to see a change but it remains black. I have also tried it using both Qt 4 and Qt 5.


Solution

  • When drawing a QPixmap to a QGLWidget, OpenGL textures are used. The OpenGL platform will have a maximum texture size, and most likely your image is exceeding this limit.

    An easy fix is to subdivide the pixmap into smaller tiles, add them to the QGraphicsScene, then group them:

    QPixmap pixmap(":/images/chart.png");
    QSize tileSize(512, 512);
    QList<QGraphicsItem *> tiles;
    for(int y = 0; y < pixmap.height(); y += tileSize.height())
    {
        for(int x = 0; x < pixmap.width(); x+= tileSize.width())
        {
            int w = qMin(tileSize.width(), pixmap.width() - x);
            int h = qMin(tileSize.height(), pixmap.height() - y);
    
            QGraphicsItem *tile = scene->addPixmap(pixmap.copy(x, y, w, h));
            tile->setPos(x, y);
            tiles.append(tile);
          }
     }
     QGraphicsItem *pixmapItem = scene->createItemGroup(tiles);
    

    This results in pixmapItem pointing to a group of pixmaps that can be treated as a single unit. Be sure to choose a suitable tile size smaller than the maximum texture size.