PDA

View Full Version : QGraphicsItem pos() and setpos()



jimc1200
12th March 2009, 22:00
Hi, I'm new to QT Graphics and is really confused with its coordinate system.
I'm also not sure how parent & child items relate. Below is a simplified code to illustrate my questions.

1.) In the code I created a rectangle item m_RectItem1 from the scene object. Now when I check retangle1's position using pos(), it's giving me (0,0).Why is this? Shouldn't it be (100,100)? Documentation says that pos() is parent's coordinate .It appears that on each item that is added in the scene, pos() is always (0,0) which is not how the output looks like (which is obviously 100,100) :confused:

2.)I created another rectangle item m_RectItem2's and then set it's parent to m_RectItem1. I then set it's position to (0,0). From what I understood in the documenation, the child should be centered on it's parent's (0,0), however this is not the case, m_RectItem2 is still drawn outside its parent m_RectItem1. Can anyone explain?

Will greatly appreciate any enlightenment on these questions. Thanks!


GraphicsTestApp::GraphicsTestApp(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);

m_Scene = new QGraphicsScene();
m_Scene->setSceneRect ( 0, 0, 500, 500 ) ;
m_RectItem1 = m_Scene->addRect(QRectF(100,100,50,100));
m_RectItem2 = m_Scene->addRect(QRectF(10,10,10,10));
m_RectItem2->setParentItem(m_RectItem1);
m_RectItem2->setPos(0,0);

qDebug() << m_RectItem1->scenePos();
qDebug() << m_RectItem1->pos();
qDebug() << m_RectItem1->boundingRect();

qDebug() << m_RectItem2->scenePos();
qDebug() << m_RectItem2->pos();
qDebug() << m_RectItem2->boundingRect();


ui.graphicsView->setScene(m_Scene);
}

wysota
12th March 2009, 22:15
1.) In the code I created a rectangle item m_RectItem1 from the scene object. Now when I check retangle1's position using pos(), it's giving me (0,0).Why is this? Shouldn't it be (100,100)?
No, (0,0) is correct. There are two different things when speaking about coordinates.

One is a local coordinate system that is described by the item's boundingRect() - in your case the item's coordinates range from (100,100) to (150,200).

Another thing is the position of the item relative to its parent - this is what pos() and setPos() operate on. In your situation the position is (0,0) as it is the default position unless you change it. It means that point (0,0) of the item's local coordinate system is mapped to point (0,0) aka 'the position' of the parent's coordinate system. In other words setPos() determines where the origin of the item's coordinate system will be placed relative to the parent.


Documentation says that pos() is parent's coordinate .It appears that on each item that is added in the scene, pos() is always (0,0) which is not how the output looks like (which is obviously 100,100) :confused:
It's exactly how it looks. It's just that your item begins at its own (100,100) point, so it's moved to the right.


2.)I created another rectangle item m_RectItem2's and then set it's parent to m_RectItem1. I then set it's position to (0,0). From what I understood in the documenation, the child should be centered on it's parent's (0,0)
No, the item's (0,0) point will cover the (0,0) point of its parent. If you set the child's bounding rect to (-5,-5,10,10) it would be centered at parent's (0,0) point.

Try setting the boundingRect of the first item to (-25, -50, 50, 100) and the rect of the second item to (-5,-5,10,10). Then play with setPos().

In addition to that you might subclass the rect item class and reimplement its paint() routine so that in addition to what it normally does, it would place a point at its origin. Then it'll be easier to notice relations between positions of items.

jimc1200
14th March 2009, 01:31
Thank you wysota for the explanation.
I still have a question. If I have several rectangles on a scene, how would I save the locations and be able to recreate them again? The boundingRect() doesn't seem to change when the items are moved around the scene. Thanks.

jimc1200
14th March 2009, 08:16
Looks like sceneBoundingRect () was the right method to use instead of boundingRect(). :)

wysota
14th March 2009, 09:07
Not really. You should save boundingRect(), pos() and transformation matrix to have a complete set of data needed to recreate the item. sceneBoundingRect() will return wrong values once you start rotating items.

jimc1200
16th March 2009, 18:09
Thanks Wysota.
Is it really a common practice to save boundingRect(), pos() and transformation matrix along with your graphicsitem? I was just thinking if calculations could be done with just the graphicsitem itself. So just to clarify, if I create a graphicsitem, I would need to track its current position (pos ,boundingRect etc) on a separate data structure (maybe) and then retrieve these values to do future calculations?

wysota
16th March 2009, 18:51
I don't know what you are trying to achieve so it is hard to answer this question. The boundingRect is a coordinate space of the item and the item itself always operates in its own coordinate space. So if you rotate a parent item, all its child items get rotated although they still think they have the same coordinates as before.

Let's consider an example - the Earth spins around the Sun so absolute (actually relative to the Solar System) coordinates of each place on Earth change all the time. But we don't care as we are subject to the same changes ourselves (we're bound to Earth's coordinate system) so we can still use Earth's coordinates - planes can reach their cities of destination without compensating for Earth's trip around the Sun or around its own axis. Now let's have a broader look - the Sub spins around the centre of the Milky Way galaxy so it's coordinates change all the time and these changes also influence absolute coordinates of places on Earth. But people on Earth don't have to care about it, they always use their local (Earth's) coordinate space. That's the same with Graphics View - the item only "sees" its own coordinates relative to its parent just like people see world from their own perspective relative to their "parent object" which is Earth. If you want to recreate your position on Earth, you need to know the lat. and long. coordinates and height above sea level (equivalent of QGraphicsItem::pos()) but you also need to know how tall you are, which side you are facing, what is the colour of your skin, your name, etc. You have to store all that data somewhere - otherwise it would not be possible to distinguish between you and some other person if (s)he occupied the same coordiantes as you. Those attributes are the item's boundingRect, color, brush, etc. The more precisely you want to recreate an item, the more data about it you need to store. It is up to you how much data to store and what to recreate afterwards.