1
votes

I want to draw colored tiles as background for a QGraphicsscene and provide pan and zoom functionality for the scene using a QGraphicsView. First I used QGraphicItems to draw each tile. Since I have many tiles this was quite a performance problem when panning or zooming but since I do not need to modify any part of the tiles afterwards I switched to generating a QPixmap using the following code:

void plotGrid(){
    Plotable::GraphicItems items;
    append(items,mParticleFilter.createGridGraphics());
    append(items,mParticleFilter.getRoi().mRectangle.createGraphics(greenPen()));
    scaleItems(items,1.0,-1.0);
    QGraphicsScene scene;
    showItemsOnScene(items,&scene);
    QRectF boundingRect = scene.itemsBoundingRect();
    double cScale = ceil(1920.0/boundingRect.size().width());
    QSize size(boundingRect.size().toSize()*cScale);
    QPixmap pixmap(size);
    pixmap.fill(Qt::transparent);
    QPainter p(&pixmap);
    //p.setRenderHint(QPainter::Antialiasing);
    scene.render(&p);
    p.end();
    QGraphicsPixmapItem* item = new QGraphicsPixmapItem(pixmap);
    item->setOffset(boundingRect.topLeft()*cScale);
    item->scale(1/cScale,1/cScale);
    mpView->showOnScene(item);
  }

While this solves the zoom and pan problem, the time to generate the pixmap introduces some significant delay, probably because I first create a scene and then render it. Is there a faster way of producing a QPixmap on the fly starting from QGraphicItems ?

Just for completeness an image of the tiles: enter image description here

1

1 Answers

0
votes

So I finally got at least past using an intermediary scene. The following code only relies on a QPainter for rendering the pixmap. My main problem was to get all transformations right. Otherwise it is quite straight forward.... This version halves the processing time to 500ms in my scenario. 450ms are spent on painting the items. If someone has more suggestions for more improvement it would be most welcome (cahnging the resolution does not help much by the way)

void SceneWidget::showAsPixmap(Plotable::GraphicItems const& items){
    QRectF boundingRect;
    boostForeach(QGraphicsItem* pItem,items) {
      boundingRect = boundingRect.united(pItem->boundingRect());
    }
    QSize size(boundingRect.size().toSize());
    double const cMaxRes =1920;
    double const scale = cMaxRes/boundingRect.size().width();
    QPixmap pixmap(size*scale);
    pixmap.fill(Qt::transparent);
    QPainter p(&pixmap);
    //p.setCompositionMode( QPainter::CompositionMode_Source );
    p.translate(-boundingRect.topLeft()*scale);
    p.scale(scale,scale);
    QStyleOptionGraphicsItem opt;
    boostForeach(QGraphicsItem* item,items) {
      item->paint(&p, &opt, 0);
    }
    p.end();
    QGraphicsPixmapItem* item = new QGraphicsPixmapItem(pixmap);
    item->scale(1.0/scale,-1.0/scale);
    item->setOffset(boundingRect.topLeft()*scale);
    showOnScene(item);
}