In case someone’s interested, here’s how I ended up doing this. It was only tested in my own special case where it works, it might not work properly elsewhere. The draw order is important.. anyway:
void renderItem(QGraphicsItem* item, QPainter* painter,
QStyleOptionGraphicsItem* option,
const QTransform& baseTransform)
{
QTransform itemTransform = item->sceneTransform();
itemTransform *= baseTransform;
painter->setWorldTransform(itemTransform, false);
item->paint(painter, option, NULL);
// Recurse into children
//TODO this should be breadth-first not depth-first!
foreach ( QGraphicsItem* child, item->childItems() )
{
renderItem(child, painter, option, baseTransform);
}
}
void Capture::save(QDeclarativeItem* item)
{
delete m_pixmap;
m_pixmap = NULL;
m_pixmap = new QPixmap(item->width(), item->height());
QPainter painter(m_pixmap);
QStyleOptionGraphicsItem option;
// Get the inverse transform of the root item's scene transform; all the
// children's transforms will be transformed by this in order to bring
// their coordinate systems from the scene space to the root item space
QTransform inverse = item->sceneTransform().inverted();
// Recursively render the item and all its children
renderItem(item, &painter, &option, inverse);
}
So the beef is that we’re grabbing the scene transforms (which indicated how the items are positioned / oriented in relation to the root window/“scene”) of each item and setting that to the painter. We’re also transforming those transforms by the inverse transform of the root item we’re drawing to bring the coordinate systems from the “scene space” into the root item’s coordinate space.
- Matti
ps. EDIT: could we please have the annotated code block to always (independent of the browser window width) allow for at least 80 characters per line without wrapping the lines? Would make the code whole lot more readable.
↧