I have a QGraphicsRectItem item in a QGraphicsScene.
The item is movable and has no parent.
I place the item reading positions from file and calling the constructor:
item = new QGraphicsRectItem (rect);
that works. Positions are as intended.
Then I try to store position back to file by getting it from the item using
item->pos().toPoint()
The position is wrong - not the absolute position in scene. The position is relative to the last position, where the item was created.
Is pos() right method for retrieving the item position within the scene?
Thank you for any hints!
P.S.:
scenePos() returns the same values
I've had problems with QGraphicsRectItem as well. My current hypothesis is this:
The "rect" that you set/get is relative to the item's "pos", so you can use one or the other (or both if you want to get confused) to control the location at which the geometry is actually drawn.
My solution was this:
// Given QRectF scene_rect that represents the rectangle I want drawn...
setPos( scene_rect.topLeft() ); // Set the item's "position" relative to the scene
scene_rect.moveTo( 0.0, 0.0 ); // ...then set the rectangle's location to (0,0)
setRect( scene_rect ); // ...so the rectangle is drawn at (0,0) relative to the item
I found your question because I was searching the web on hints which of both to use.
I took a look at the Qt 4.7.4 sources:
QGraphicsRectItemPrivate
has a member QRectF rect
which you can get with rect() and change with setRect().
- But, as it is derived from
QGraphicsItem
, it also has a QRectF pos
.
- The function
boundingRect()
returns rect
adjusted by pen width, which means that the area to be updated is generally correct.
So, as aldo said, you have to decide if you use rect.topLeft or pos for positioning.
To help you and others decide, here are a few pro and contra points:
Advantages of using rect:
- You can define the position and size of the QGraphicsRectItem in one function call.
- In case of
QGraphicsLineItem
, the pos() function always points to the topLeft corner of the boundingRect, which doesn't have to be one of the line points, so by leaving pos at QPointF(0,0), the QLine points are always relative to the scene.
Disadvantage of using rect:
- Because you can't use setPos(), there is no function that emits a
QGraphicsItem::ItemPositionChange
. To me, this point weighs more than the advantages, as long as you're not using a QGraphicsLineItem (If I'd need a QGraphicsLineItem, I'd probably derive from it and send the QGraphicsItem::ItemPositionChange myself).
How and when to use both:
If you use both pos and rect, let pos be the center of your GraphicsItem.
Imagine a marker, cursor or similar with a specific radius in your graphics scene. If you want to use QGraphicsRectItem
for that, I suggest:
QPointF markerpos = GetMarkerPos();
double r = GetMarkerRadius();
QRectF markerrect(-r, -r, +r * 2., +r * 2.); // topleft: -radius, size: 2*radius
setPos(markerpos);
setRect(markerrect);
This way, the pos always points to the center and the rect is only defined by the radius.
Now I found the workaround. Don't knot if it is bug of Qt or my misunderstanding on scene/view.
Now I create the items at the position 0,0 and move them to desired position using moveBy(x,y).
item = new QGraphicsRectItem( QRect(QPoint(x,y),QSize(w,h)) );
QPoint p = item->pos().toPoint(); //WRONG position! Relative to x,y
item = new QGraphicsRectItem( QRect(QPoint(0,0),QSize(w,h)) );
item->moveBy(x,y);
QPoint p = item->pos().toPoint(); //Right position! Relative to 0,0 of scene
Weird, somehow.