I have QGraphicsItems
on a QGraphicsScene
. I need to group them. The main reason for grouping: I need to provide a way to apply transformations on a group.
It is all very simple if I need to apply a single transformation, and the items bounding rectangle top-left is at 0,0.
I have seen how grouping and ungrouping works, preserving items' transformations relative to the scene, and that is great. But on grouping, no matter what positions my items have, the group has coordinates (0,0).
When I try any transformations, no matter what I tried with the transformation origin point, the item moves.
Simple program to show:
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene s;
QGraphicsView view(&s);
s.setSceneRect(90, -10, 420, 140);
view.show();
QGraphicsRectItem* sceneR = new QGraphicsRectItem(s.sceneRect());
s.addItem(sceneR);
QTransform t; // simple scaling transform
t.scale(2, 1); // adding rotation scares me
QGraphicsRectItem* r0 = new QGraphicsRectItem(QRectF(0, 0, 150, 100)); // for compare, not scaled
r0->setBrush(QBrush(Qt::red));
r0->setPos(100, 0);
s.addItem(r0);
QGraphicsRectItem* r1 = new QGraphicsRectItem(QRectF(0, 0, 150, 100)); // for compare, not scaled
r1->setBrush(QBrush(Qt::blue));
r1->setPos(100, 10);
s.addItem(r1);
QGraphicsRectItem* r2 = new QGraphicsRectItem(QRectF(0, 0, 150, 100)); // will make a group of a single item
r2->setFlags(QGraphicsItem::ItemIsSelectable);
r2->setBrush(QBrush(Qt::green));
r2->setPos(100, 20);
r2->setSelected(true);
s.addItem(r2);
QGraphicsItemGroup* g = s.createItemGroup(s.selectedItems());
// QPointF topLeft = g->mapToScene(g->boundingRect().topLeft());
// g->setTransformOriginPoint(topLeft);
r1->setTransform(t);
g->setTransform(t);
qDebug() << r1->pos() << r1->transform();
qDebug() << g->pos() << g->transform();
return app.exec();
}
If I apply transformations, the grouped item moves. I have not been able to figure out a logic or how to compensate.
(red = reference, not scaled; blue, reference, scaled; green, grouped and scaled)
In image above I expect the green rectangle to have the same x coordinate as the blue (I shifted vertically to see what is going on)
How can I make my scaling (and rotation) in place ?
(I am considering the alternative of just setting a common parent, and performing all the work to retrieve items transformations, but not sure how to combine them properly, especially scaling a group how to find the new position and new scale of inside items)
Found a solution - even though I am counting on the group to perform item transformations and calculate its own edges, I must do it manually as well.
Steps:
I find the top-left most point (minX, minY)
of selected items' bounding rectangles (mapped to scene),
then move all items by -minX, -minY
,
then after grouping, move group by minX, minY
.
This sets a correct center of transformations, so the group item behaves like regular items. It also reports a pos()
in its top left corner, similar to the default pos()
of other QGraphicsItems
.