setPos Problem with a custom QGraphicsItemGroup
-
I'm running into problems with calling setPos in a custom QGraphicsItemGroup class.
QRectF myGroup::boundingRect() { return childrenBoundingRect(); }
When I call the following setPos multiple times, it will not stay in the same place but will drift across my scene.
setPos(mapToScene(100, 100));
The only success I've had is the following:
void myGroup::SetGroupPos(QPointF newPos) { setPos(0,0); foreach(QGraphicsItem* item, childItems()) { item->setPos(newPos); } }
Any suggestion on what I may have messed up?
-
@w.h. said:
boundingRect
Are you sure you followed documentation requirement in your item:
QGraphicsScene expects all items boundingRect() and shape() to remain unchanged unless it is notified. If you want to change an item's geometry in any way, you must first call prepareGeometryChange() to allow QGraphicsScene to update its bookkeeping.
-
I did some further testing with standard(non-custom) QGraphicsItem and QGraphicsItemGroup and it seems like they act like my custom items. I'm using Qt version 5.2. Is this how QGraphicsItemGroup is suppose to act? Why is the initial position of the group is always (0,0) no matter the the positions of the children? What am I missing?
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); gs = new QGraphicsScene; ui->graphicsView->setScene(gs); rect = new QGraphicsRectItem(0,0,50,100); rect->setPos(200,200); cir = new QGraphicsEllipseItem(0, 0, 100, 100); cir->setPos(200, 200); gs->additem(rect); gs->addItem(cir); grp = new QGraphicsItemGroup; grp->addToGroup(rect); grp->addToGroup(cir); gs->addItem(grp); } void MainWindow::on_pushButton_clicked() { //init pos and scene Pos is QPointF(0,0) despite the //children's pos is QPointF(200,200) qDebug()<<"init pos = "<<grp->pos(); qDebug()<<"init Scene pos = "<<grp->scenePos(); grp->setPos(500, 500); //grp->setPos(ui->graphicsView->mapToScene(500,500)); //does not work...every time the button is pressed it //moves to different locations //the below shows the pos is QPointF(500,500) but the //actual pos on the scene is QPointF(700, 700) qDebug()<<"after pos = "<<grp->pos(); qDebug()<<"after Scene pos = "<<grp->scenePos(); //both the scenePos for rect and cir are changed // to QPointF(700, 700) qDebug()<<"after pos for Rect = "<<rect->scenePos(); qDebug()<<"after pos for cir = "<<cir->scenePos(); }
-
Position is given in the coordinate system of the group's parent (which might be the scene, if the group is directly added to the scene).
Now the group's position is a reference that doesn't change by adding children. Think of the group as a piece of paper you place on a desk. Draw something in the middle of the paper, and the position of the paper itself is still the same.
What you probably want is to add the children, set the children's position to 0/0 and the group's position to 200/200, not the other way round.
When you say the following code moves the group around:
setPos(mapToScene(100, 100));
then it's important to know in which context that code is called. This can very well lead to a "drift" effect, because you are setting a position (which is in the item's parent's coordinate system) using a function which delivers a scene position - i.e. you are potentially mixing up coordinate systems.The following illustration in the docs, under 'The Graphics View Coordinate System' is helpful:
If you call setPos of "3", you need to so so in the context of "2".