Results 1 to 11 of 11

Thread: Question about QGraphicsRectItem

  1. #1
    Join Date
    Dec 2006
    Posts
    426
    Thanks
    8
    Thanked 18 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default 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..

    Qt Code:
    1. #include <QApplication>
    2. #include <QGraphicsScene>
    3. #include <QGraphicsView>
    4. #include <QGraphicsRectItem>
    5.  
    6. int main( int argc, char** argv )
    7. {
    8. QApplication app(argc, argv);
    9.  
    10. scene.setSceneRect( 0, 0, 500, 500 );
    11.  
    12. QGraphicsRectItem outerRect;
    13. outerRect.setRect( QRectF( 20, 20, 400, 400 ) );
    14.  
    15. QGraphicsRectItem innerRect;
    16. innerRect.setRect( QRectF( 0, 0, 200, 400 ) );
    17. innerRect.setParentItem( &outerRect );
    18. innerRect.setPen( QPen( Qt::red ) );
    19.  
    20. scene.addItem( &outerRect );
    21.  
    22. QGraphicsView view(&scene);
    23.  
    24. view.show();
    25.  
    26. return app.exec();
    27.  
    28. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2006
    Posts
    132
    Thanked 16 Times in 16 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Question about QGraphicsRectItem

    What happens if you set the geometry of the second rectangle after making it child of the first?

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default 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.

  4. #4
    Join Date
    Dec 2006
    Posts
    426
    Thanks
    8
    Thanked 18 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Question about QGraphicsRectItem

    Quote Originally Posted by wysota View Post
    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:
    Qt Code:
    1. #include <QApplication>
    2. #include <QWidget>
    3. #include <QGraphicsScene>
    4. #include <QGraphicsView>
    5. #include <QGraphicsRectItem>
    6. #include <QGroupBox>
    7. #include <QFrame>
    8.  
    9. static void testWidgetRect()
    10. {
    11. QWidget* root = new QWidget;
    12. root->setGeometry(QRect(0, 0, 500, 500));
    13.  
    14. QPalette palette;
    15. QBrush brush( Qt::white );
    16. palette.setBrush(QPalette::Inactive, QPalette::Window, brush);
    17. palette.setBrush(QPalette::Active, QPalette::Window, brush);
    18. root->setPalette(palette);
    19. root->setAutoFillBackground(true);
    20.  
    21. QWidget* frame = new QFrame(root);
    22. frame->setGeometry(QRect(20, 20, 400, 400));
    23.  
    24. QPalette palette1;
    25. QBrush brush1( Qt::black );
    26. palette1.setBrush(QPalette::Inactive, QPalette::Window, brush1);
    27. palette1.setBrush(QPalette::Active, QPalette::Window, brush1);
    28. frame->setPalette(palette1);
    29. frame->setAutoFillBackground(true);
    30.  
    31. QWidget* groupBox = new QGroupBox(frame);
    32. groupBox->setGeometry(QRect(5, 5, 200, 400 ));
    33.  
    34. QPalette palette2;
    35. QBrush brush2( Qt::red );
    36. palette2.setBrush(QPalette::Inactive, QPalette::Window, brush2);
    37. palette2.setBrush(QPalette::Active, QPalette::Window, brush2);
    38. groupBox->setPalette(palette2);
    39. groupBox->setAutoFillBackground(true);
    40.  
    41. root->setWindowTitle( "testWidgetRect" );
    42. root->show();
    43. }
    44.  
    45. static void testGraphicsRect()
    46. {
    47. // test graphics
    48. scene->setSceneRect( 0, 0, 500, 500 );
    49.  
    50. outerRect->setRect( QRectF( 20, 20, 400, 400 ) );
    51. outerRect->setBrush( QBrush( Qt::black ) );
    52.  
    53. innerRect->setRect( QRectF( 5, 5, 200, 400 ) );
    54. innerRect->setParentItem( outerRect );
    55. innerRect->setPen( QPen( Qt::red ) );
    56. innerRect->setBrush( QBrush( Qt::red ) );
    57.  
    58. scene->addItem( outerRect );
    59.  
    60. QGraphicsView* view = new QGraphicsView(scene);
    61.  
    62. view->setWindowTitle( "testGraphicsRect" );
    63. view->show();
    64.  
    65. }
    66.  
    67. int main( int argc, char** argv )
    68. {
    69. QApplication app(argc, argv);
    70.  
    71. // test widget
    72. testWidgetRect();
    73.  
    74. // test graphics
    75. testGraphicsRect();
    76.  
    77. return app.exec();
    78.  
    79. }
    To copy to clipboard, switch view to plain text mode 

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default 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.

  6. #6
    Join Date
    Dec 2006
    Posts
    426
    Thanks
    8
    Thanked 18 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Question about QGraphicsRectItem

    Quote Originally Posted by wysota View Post
    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":

    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.

  7. #7
    Join Date
    Dec 2006
    Posts
    426
    Thanks
    8
    Thanked 18 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default 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...

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Question about QGraphicsRectItem

    Quote Originally Posted by lni View Post
    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.

    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:
    Qt Code:
    1. static void testGraphicsRect()
    2. {
    3. // test graphics
    4. scene->setSceneRect( 0, 0, 500, 500 );
    5.  
    6. outerRect->setRect( QRectF( 0, 0, 400, 400 ) );
    7. outerRect->setBrush( QBrush( Qt::black ) );
    8.  
    9. innerRect->setRect( QRectF( 0, 0, 200, 400 ) );
    10. innerRect->setParentItem( outerRect );
    11. innerRect->setPos(5,5);
    12. innerRect->setPen( QPen( Qt::red ) );
    13. innerRect->setBrush( QBrush( Qt::red ) );
    14.  
    15. scene->addItem( outerRect );
    16. outerRect->setPos(20,20);
    17. QGraphicsView* view = new QGraphicsView(scene);
    18.  
    19. view->setWindowTitle( "testGraphicsRect" );
    20. view->show();
    21.  
    22. }
    To copy to clipboard, switch view to plain text mode 

  9. #9
    Join Date
    Dec 2006
    Posts
    426
    Thanks
    8
    Thanked 18 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Question about QGraphicsRectItem

    Quote Originally Posted by wysota View Post
    You are simply using the item in a wrong way. QGraphicsRectItem::setRect() is not equivalent to QWidget::setGeometry()!
    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

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Question about QGraphicsRectItem

    Quote Originally Posted by lni View Post
    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.

    Another question about setPos and translate: it appears that both functions have exactly the same visual effect.
    Yes, that's correct.
    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.

    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.

    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.

  11. #11
    Join Date
    Dec 2006
    Posts
    426
    Thanks
    8
    Thanked 18 Times in 17 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Question about QGraphicsRectItem

    Quote Originally Posted by wysota View Post
    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 View Post
    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!

Similar Threads

  1. Plugin implementation question
    By JPNaude in forum Qt Programming
    Replies: 12
    Last Post: 27th August 2008, 20:24
  2. SQL Question
    By ^NyAw^ in forum Qt Programming
    Replies: 5
    Last Post: 8th April 2008, 19:36
  3. Access to QSqlTableModel::isDirty Question.
    By patrik08 in forum Qt Programming
    Replies: 3
    Last Post: 12th April 2007, 17:49
  4. Replies: 1
    Last Post: 15th March 2007, 20:45

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.