Rendering QGraphicsItem into QPixmap

I was in need of rendering a QGraphicsItem into a QPixmap outside of the QGraphics framework. Although the final solution is simple, it took me a while to get it right. As Google wasn’t much of a help here I decided to publish my solution to the problem here.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
QPixmap MyGraphicsItem::toPixmap()
{
    // Retrieve the bounding rect
    QRect rect = boundingRect().toRect();
    if (rect.isNull() || !rect.isValid()) {
        return QPixmap();
    }
 
    // Create the pixmap
    QPixmap pixmap(rect.size());
    pixmap.fill(Qt::transparent);
 
    // Render
    QPainter painter(&pixmap);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setRenderHint(QPainter::TextAntialiasing, true);
    painter.translate(-rect.topLeft());
    paint(&painter, nullptr, nullptr);
    for (QGraphicsItem* child : childItems()) {
        painter.save();
        painter.translate(child->mapToParent(pos()));
        child->paint(&painter, nullptr, nullptr);
        painter.restore();
    }
 
    painter.end();
 
    return pixmap;

The least obvious part is that we have to take care of rendering the children ourselves. This isn’t that obvious because that is usually taken care of automatically by the QGraphics framework. However, as the goal is to render the QGraphicsItem outside of the QGraphics framework we have to handle it manually. This also includes taking care of translating between the coordinate systems as each QGraphicsItem maintains its own coordinate system. Furthermore, a check has been added to abort the process if the item has either a null or an invalid bounding rectangle. Otherwise the painting operation will fail and throw a warning because there is no surface to paint on:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
QPainter::begin: Paint device returned engine == 0, type: 2
QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::translate: Painter not active
QPainter::setOpacity: Painter not active
QPainter::setPen: Painter not active
QPainter::setBrush: Painter not active
QPainter::worldTransform: Painter not active
QPainter::translate: Painter not active
...
QPainter::end: Painter not active, aborted

It is worthwhile to note that we don’t have to use any recursion for painting the children: QGraphicsItem::childItems() returns a list of all child items (also the children of the children) already sorted in correct Z-Order.

This code has been tested successfully on Qt 5.7. Feel free to use this code for what ever you want.

comments powered by Disqus