PDA

View Full Version : QGraphicsItem meaning of pos(), scenePos()



nicolas1
5th October 2008, 10:47
Hello,

I have a custom class derived from QGraphicsItem. Then I call setPos(), then make rotate() on 90 degrees around specified point ( sequence: translate() ; rotate() ; translate() ). What is the meaning of pos(), scenePos() after this? Item does not have any parent item and value of pos() and scenePos() is different. But boundingRect() gives correct values.

Object is custom image item, rectangular area.
How to rotate object of class derived from QGraphicsItem correctly?

In case of QGraphicsPixmapItem what does setPos() mean? Left top point?

QbelcorT
5th October 2008, 15:55
Hi
Take a look at this link, it describes the Coordinate system in a Scene
http://doc.trolltech.com/4.4/graphicsview.html#the-graphics-view-coordinate-system
The setPos() is relative to the scene. If you have a parent to that item, then setPos() would be relative to that item at (0,0).

You can use the QGraphicsItem::SetTransform to rotate, scale, translate
http://doc.trolltech.com/4.4/qgraphicsitem.html#setTransform

Check out the examples/Graphicsview, it shows how to manipulate items. I am using a QGraphicsItem and I am able to scale only that item.

nicolas1
5th October 2008, 22:16
Qt code is quite different:



QPointF QGraphicsItem::pos() const
{
return d_ptr->pos;
}

QPointF QGraphicsItem::scenePos() const
{
return mapToScene(0, 0);
}

QTransform QGraphicsItem::sceneTransform() const
{
QTransform m = transform() * QTransform().translate(d_ptr->pos.x(), d_ptr->pos.y());
if (d_ptr->parent)
return m * d_ptr->parent->sceneTransform();
return m;
}

QTransform QGraphicsItem::transform() const
{
if (!d_ptr->hasTransform)
return QTransform();
return qVariantValue<QTransform>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform));
}


if transform() has translation (dx, dy) and other components, then some problem how to make setPos() correctly...

QbelcorT
6th October 2008, 00:40
Hello.
I don't see a reason to reimplement the pos() and scenepos(). I didn't need to. Take a look at this example. It is straight from the QtEmbedded./examples/graphicsview directory. It has the same concept of subclassing a graphicsitem (RectangleItem) and uses a transformation on it.

nicolas1
6th October 2008, 05:20
Transformation works fine. Problem is that I need to correct item position related to other items after calling rotate() (changing item's transfom).
Everything works fine when item's transformation is not changed (such as by rotate()).
I get position of other items by sceneBoundingRect().
Than I get scenePos() of item to move and its sceneBoundingRect(), then I calculate new scene coordinate item to move based on coordinates of other items (sceneBoundingRect()) and then I call setPos() to move item. Item goes to the incorrect position.
sceneCoordinate seems to be a sum of item transform and translation based on setPos().

Anyway, it is strange to have setPos() function and translate(). 2 ways to define translation.

wysota
6th October 2008, 07:29
Problem is that I need to correct item position related to other items after calling rotate() (changing item's transfom).
Why? Maybe try rotating first and only then calling setPos() instead of doing it the other way round if you want fine control over the item position?


Everything works fine when item's transformation is not changed (such as by rotate()).
I get position of other items by sceneBoundingRect().
You should rarely need to use that method at all. What is your use case?


Anyway, it is strange to have setPos() function and translate(). 2 ways to define translation.

That's not it. setPos() maps the point (0,0) of an item to parent's (0,0) point. translate() is purely for completeness and I don't see any point of using it other than rotating around a specified point in the item. translate() modifies the item matrix, setPos() doesn't - that's the difference.

nicolas1
6th October 2008, 07:56
Program I develop is interactive editor. So, setPos() and rotate() are used frequently in the order which user decides.

By sceneBoundingRect() I detect item position in scene relating to other items to estimate correct user's interactive move by mouse.

So, how to setPos() correctly after rotating item around its center? setPos() I mean to set item position programmatically.

Should I decrease value by item->transform().dx() and item->transform().dy() ?
Also it is necessary to take care of signs (decrease or increase)

In my case items do not have parents.

wysota
6th October 2008, 08:11
Program I develop is interactive editor. So, setPos() and rotate() are used frequently in the order which user decides.
But how is that related to other items on the scene?


By sceneBoundingRect() I detect item position in scene relating to other items to estimate correct user's interactive move by mouse.
But why? If you want scene coordinates, handle the event in the scene and not in the item. Anyway I see no point in knowing scene coordinates while handling mouse move.


So, how to setPos() correctly after rotating item around its center? setPos() I mean to set item position programmatically.

Should I decrease value by item->transform().dx() and item->transform().dy() ?
Also it is necessary to take care of signs (decrease or increase)

You shouldn't need to do anything. Can you provide a snippet of code (or better yet a small compilable example) to show us what you are trying to do? Basically if we want to correct item position, we tend to do it in itemChange() not in mouse move events.

nicolas1
6th October 2008, 12:26
For example, one item is rectangular and second item (picture) is inside.
User press the button and picture item needs to be enlarged but not more than rectangular item. That's why I need to correct item position and size.

Also item can be rotated, also picture item can be enlarged but no more then rectangular item.

I can get rectangulat item position and size by sceneBoundingRect().

Maybe thaere is another way to do my task...

wysota
6th October 2008, 13:20
For example, one item is rectangular and second item (picture) is inside.
So one should be child of the other and the problem disappears.


User press the button and picture item needs to be enlarged but not more than rectangular item. That's why I need to correct item position and size.
That you can control from within itemChange(), even without parent-child relationship between the items using different collision modes.

Also note a difference between boundingRect and shape.

nicolas1
9th October 2008, 04:18
I need to correct picture item position and size according to rect item and some rule.

When picture item's transform is identity, rect item's sceneBoundingRect() and picture item's sceneBoundingRect() is used well to calculate coordinate for setPos() and changing size.

When picture item is rotated (transform has dx, dy and rotation) it is impossible to use setPos() to rotated picture item, because it will result in different item position.
Different position is result of summation of item's d_ptr->pos() and item's transform.

How to calculate right coordinate, based on sceneBoundingRect() or maybe some other members, for setPos() of rotated picture item?

wysota
9th October 2008, 08:59
When picture item is rotated (transform has dx, dy and rotation) it is impossible to use setPos() to rotated picture item, because it will result in different item position.
Different position is result of summation of item's d_ptr->pos() and item's transform.
If you only use scaling and rotating and the origin is in the middle of the item, setPos shoud be transparent to them. Could you provide a minimal compilable example reproducing your problem?