QGraphicsItem returns wrong position in scene. (Qt

2019-05-17 09:03发布

问题:

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

回答1:

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


回答2:

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.



回答3:

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.



标签: qt4