Question about QGraphicsRectItem
Hi,
I have an outer QGraphicsRectItem and inner QGraphicsRectItem, where the outerRec is the parent of innerRect. When I do setRect, I would expect the rect is in respect to its parent item, but it is not the case, as shown in the example, where the red innerRect is outside its container and its position is related to the scene. Is this a bug? If it is a feature, then why not use setSize + translate? Currently the outerRect's rect has no meaning to the innerRect..
Code:
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
int main( int argc, char** argv )
{
scene.setSceneRect( 0, 0, 500, 500 );
outerRect.
setRect( QRectF( 20,
20,
400,
400 ) );
innerRect.
setRect( QRectF( 0,
0,
200,
400 ) );
innerRect.setParentItem( &outerRect );
innerRect.
setPen( QPen( Qt
::red ) );
scene.addItem( &outerRect );
view.show();
return app.exec();
}
Re: Question about QGraphicsRectItem
What happens if you set the geometry of the second rectangle after making it child of the first?
Re: Question about QGraphicsRectItem
The code works correctly. setRect() only sets the coordinate system of an item. You have to then position the item using setPos(), otherwise the child item is put in such a place so that its (0,0) point matches the (0,0) point of its parent which is exactly the effect you observe.
Re: Question about QGraphicsRectItem
Quote:
Originally Posted by
wysota
The code works correctly. setRect() only sets the coordinate system of an item. You have to then position the item using setPos(), otherwise the child item is put in such a place so that its (0,0) point matches the (0,0) point of its parent which is exactly the effect you observe.
Try this, you got inconsistent behavior:
Code:
#include <QApplication>
#include <QWidget>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QGroupBox>
#include <QFrame>
static void testWidgetRect()
{
root
->setGeometry
(QRect(0,
0,
500,
500));
root->setPalette(palette);
root->setAutoFillBackground(true);
frame
->setGeometry
(QRect(20,
20,
400,
400));
frame->setPalette(palette1);
frame->setAutoFillBackground(true);
groupBox
->setGeometry
(QRect(5,
5,
200,
400 ));
groupBox->setPalette(palette2);
groupBox->setAutoFillBackground(true);
root->setWindowTitle( "testWidgetRect" );
root->show();
}
static void testGraphicsRect()
{
// test graphics
scene->setSceneRect( 0, 0, 500, 500 );
outerRect
->setRect
( QRectF( 20,
20,
400,
400 ) );
outerRect
->setBrush
( QBrush( Qt
::black ) );
innerRect
->setRect
( QRectF( 5,
5,
200,
400 ) );
innerRect->setParentItem( outerRect );
innerRect
->setPen
( QPen( Qt
::red ) );
innerRect
->setBrush
( QBrush( Qt
::red ) );
scene->addItem( outerRect );
view->setWindowTitle( "testGraphicsRect" );
view->show();
}
int main( int argc, char** argv )
{
// test widget
testWidgetRect();
// test graphics
testGraphicsRect();
return app.exec();
}
Re: Question about QGraphicsRectItem
Widgets and graphics items have different ways of using the geometry so it is natural you will get different results when setting the same values. Widgets always have a rectangle of (0,0,width(), height()) whereas graphics items do not. The origin of the coordinate system of the black graphics item lies outside of the item itself thus the red item is positioned to the left and up of its parents top left corner.
Re: Question about QGraphicsRectItem
Quote:
Originally Posted by
wysota
Widgets and graphics items have different ways of using the geometry so it is natural you will get different results when setting the same values. Widgets always have a rectangle of (0,0,width(), height()) whereas graphics items do not. The origin of the coordinate system of the black graphics item lies outside of the item itself thus the red item is positioned to the left and up of its parents top left corner.
I thought graphics items always have a boundingRect(), which must be implemented by derived class? That boundingRect should be treated no difference from widget rect...Not to mention my example used a rectangle item...
Parent item is child item's container, therefore the child can't go outside its parent boundary, and here is the document in "The Graphics View Framework":
Quote:
Child coordinates are relative to the parent's coordinates. If the child is untransformed, the difference between a child coordinate and a parent coordinate is the same as the distance between the items in parent coordinates. For example: If an untransformed child item is positioned precisely in its parent's center point, then the two items' coordinate systems will be identical. If the child's position is (10, 0), however, the child's (0, 10) point will correspond to its parent's (10, 10) point.
Because items' position and transformation are relative to the parent, child items' coordinates are unaffected by the parent's transformation, although the parent's transformation implicitly transforms the child. In the above example, even if the parent is rotated and scaled, the child's (0, 10) point will still correspond to the parent's (10, 10) point. Relative to the scene, however, the child will follow the parent's transformation and position. If the parent is scaled (2x, 2x), the child's position will be at scene coordinate (20, 0), and its (10, 0) point will correspond to the point (40, 0) on the scene.
Re: Question about QGraphicsRectItem
The reason is that with current implementation, I have to worry about and keep track of all parent items' location related to the scene, it becomes nightmare...
In QWidget, we never have to worry about where is the parent's location, we don't care, because we know the child position is only related to its parent...
But not in QGraphicsItem, becasue all item's cordinates have the same origin, which is the scene's origin...this leaves users to manage complex QTransform all the way to the root...
Re: Question about QGraphicsRectItem
Quote:
Originally Posted by
lni
In QWidget, we never have to worry about where is the parent's location, we don't care, because we know the child position is only related to its parent...
This is exactly the case with graphics items as well.
Quote:
But not in QGraphicsItem, becasue all item's cordinates have the same origin, which is the scene's origin...
No, this is not true. You are simply using the item in a wrong way. QGraphicsRectItem::setRect() is not equivalent to QWidget::setGeometry()!
Substitute your testGraphicsRect() with this one:
Code:
static void testGraphicsRect()
{
// test graphics
scene->setSceneRect( 0, 0, 500, 500 );
outerRect
->setRect
( QRectF( 0,
0,
400,
400 ) );
outerRect
->setBrush
( QBrush( Qt
::black ) );
innerRect
->setRect
( QRectF( 0,
0,
200,
400 ) );
innerRect->setParentItem( outerRect );
innerRect->setPos(5,5);
innerRect
->setPen
( QPen( Qt
::red ) );
innerRect
->setBrush
( QBrush( Qt
::red ) );
scene->addItem( outerRect );
outerRect->setPos(20,20);
view->setWindowTitle( "testGraphicsRect" );
view->show();
}
Re: Question about QGraphicsRectItem
Quote:
Originally Posted by
wysota
Maybe the document for QGraphicsRectItem::setRect() should be more clear, I did think it was the same as setGeometry and use it as setGeometry, and now I have to toss my codes...
Another question about setPos and translate: it appears that both functions have exactly the same visual effect. I did scale and rotate after setPos and translate, both produce identical view. Can you give example where they will produce different result after some operations? I will be using a lot setPos and/or translate, I hope you can give more detailed info on them so I don't make mistake again...
Also, what is the chance to have QGraphicsAbstractBuilder and QGraphicsBuilder, just as QFormBuilder? Serializing QGraphicsScene and its content is very useful...
Many thanks
Re: Question about QGraphicsRectItem
Quote:
Originally Posted by
lni
Maybe the document for QGraphicsRectItem::setRect() should be more clear, I did think it was the same as setGeometry and use it as setGeometry, and now I have to toss my codes...
Please don't blame the docs, they are very clear about this, it's just you didn't read them carefully enough.
The Graphics View coordinate system.
Quote:
Another question about setPos and translate: it appears that both functions have exactly the same visual effect.
Yes, that's correct.
Quote:
I did scale and rotate after setPos and translate, both produce identical view. Can you give example where they will produce different result after some operations?
QGraphicsItem::pos() will probably return a different value which can be very important in many situations.
Quote:
I will be using a lot setPos and/or translate, I hope you can give more detailed info on them so I don't make mistake again...
Use setPos() and forget about translate(), it's purely for completeness.
Quote:
Also, what is the chance to have QGraphicsAbstractBuilder and QGraphicsBuilder, just as QFormBuilder? Serializing QGraphicsScene and its content is very useful...
None, I guess. There is no data format for storing graphics items. The easiest way to do serialization is to use QDataStream.
Re: Question about QGraphicsRectItem
Quote:
Originally Posted by
wysota
Please don't blame the docs, they are very clear about this, it's just you didn't read them carefully enough.
Yes, it is my careless. People tend to skip most part of document. :)
Quote:
Originally Posted by
wysota
Use setPos() and forget about translate(), it's purely for completeness.
setPos and translate are very very different and produce totally different results after several scale and translate operations. It took me 4 hours to finally find out that I should be using setPos!
You are very helpful! Thank you!