Results 1 to 20 of 21

Thread: add pixels to qgraphicsitem

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    3
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: add pixels to qgraphicsitem

    Quote Originally Posted by mcarter View Post
    If I draw the hilite inside the paint event, will it not draw outside the boundingRect?
    Physically it will be drawn but you'll get artifacts if you start manipulating your view.
    Can I adjust the boundingRect inside the paint event?
    No.

    btw, is the pen size also based on scene scaling?
    Unless you set it to cosmetic then yes.

    So if I want to change the pen size to be larger for the rectangle draw I need to adjust based on transform to get the proper pixel width? Will there be an impact if I have 100,000's of these items on the screen?
    I don't understand what you mean.

    Since I am new the this, is there a better way?
    Yes. Use a separate item was hilighting. Make it a child of your main item and adjust its geometry based on the geometry of the parent. You can even set the ItemIgnoresTransformations flag on it.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  2. #2
    Join Date
    Nov 2010
    Posts
    315
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo
    Thanked 53 Times in 51 Posts

    Default Re: add pixels to qgraphicsitem

    From my experience you should restore state of painter at the end of paint.
    Without it you can have strange artifacts. Of course if you are using some optimization flag to auto store painter then this problem will not appear.
    When you are writing own graphics item you shouldn't try to evaluate impact of transformation, especially when you have little experience with graphics freamework.

    Try correct this code like that:
    Qt Code:
    1. class MyRect : public QObject, public QGraphicsRectItem
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. MyRect( QGraphicsItem *pParent=0 )
    7. : QGraphicsRectItem( pParent )
    8. {
    9. setItUp();
    10. }
    11. MyRect( const QRectF & rect, QGraphicsItem* pParent=0 )
    12. : QGraphicsRectItem( rect, pParent )
    13. {
    14. setItUp();
    15. }
    16. ~MyRect() {}
    17.  
    18. void setItUp()
    19. {
    20. m_penWidth = 1.0;
    21. setPen( QPen(Qt::green) );
    22. setAcceptHoverEvents( true );
    23. setFlag( QGraphicsItem::ItemIsSelectable, true );
    24. }
    25.  
    26. QRectF boundingRect() const
    27. { //looks ok
    28. return this->rect().adjusted( -m_penWidth, -m_penWidth,
    29. m_penWidth, m_penWidth );
    30. }
    31.  
    32. protected:
    33. void paint( QPainter *painter,
    34. const QStyleOptionGraphicsItem *option,
    35. QWidget *widget )
    36. {
    37. Q_UNUSED(widget);
    38.  
    39. // this way is faster then painter->store();
    40. QPen oldPen = painter->pen();
    41. QBrush oldoldBrush = painter->brush();
    42.  
    43. painter->setBrush(brush());
    44. if (option->state & QStyle::State_Selected) {
    45. painter->setPen(pen());
    46. } else {
    47. QPen hilitePen(QBrush(Qt::red),m_penWidth);
    48. painter->setPen(hilitePen);
    49. }
    50. painter->drawRect(rect());
    51.  
    52. // restore painter:
    53. painter->setPen(oldPen);
    54. painter->setBrush(oldBrush);
    55. }
    56.  
    57. private:
    58. qreal m_penWidth;
    59. };
    To copy to clipboard, switch view to plain text mode 

    Another thing why you are trying do it yourself?
    Why not just manipulate properties of QGraphicsRectItem?
    Just use QAbstractGraphicsShapeItem::setBrush and QAbstractGraphicsShapeItem::setPen when state of item is changed.
    Re-implement itemChange method to react on that.
    Last edited by MarekR22; 13th February 2011 at 18:17.

  3. #3
    Join Date
    Nov 2009
    Location
    San Antonio, TX
    Posts
    69
    Qt products
    Qt4 Qt Jambi
    Platforms
    Unix/X11 Windows
    Thanked 1 Time in 1 Post

    Default Re: add pixels to qgraphicsitem

    So if I want to change the pen size to be larger for the rectangle draw I need to adjust based on transform to get the proper pixel width? Will there be an impact if I have 100,000's of these items on the screen?

    I don't understand what you mean.
    I was wondering if I start doing a lot of transform manipulation in the item, will this have an impact of I have many, many, many of these items in the view.

    Since I am new the this, is there a better way?

    Yes. Use a separate item was hilighting. Make it a child of your main item and adjust its geometry based on the geometry of the parent. You can even set the ItemIgnoresTransformations flag on it.
    This sounds like the way to go, especially with the itemIgnoresTransformation. However, I am not sure how to implement. Do I override the itemChange of the main item to update the geometry of the child? Does the child get the actual transform of the scene/view thru its paintEvent so I can scale it properly? Just need a little push to get a better handle on GV.


    Added after 6 minutes:


    MarekR22, your answer is a valid response if I was only interested in changing the color of the item rectangle. I would indeed let the item do most of the work.

    What I am looking for is a way to place a highlight rectangle around the entire item's rectangle.
    Last edited by mcarter; 13th February 2011 at 22:08.

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

    Default Re: add pixels to qgraphicsitem

    Quote Originally Posted by mcarter View Post
    I was wondering if I start doing a lot of transform manipulation in the item, will this have an impact of I have many, many, many of these items in the view.
    Yes, of course.

    This sounds like the way to go, especially with the itemIgnoresTransformation. However, I am not sure how to implement. Do I override the itemChange of the main item to update the geometry of the child?
    Probably the other way would be better. It'd be best if the "parent" had a placeholder for the "hilight item" and called some function in the item when its boundingRect() changes.

    Does the child get the actual transform of the scene/view thru its paintEvent so I can scale it properly? Just need a little push to get a better handle on GV.
    The child only has to reread the parent's bounding rect and adjust itself to it. If you make the child a "resizer item" (with anchors that resize the main item when you drag them) it's even simpler as the child can then control the parent without any special treatment from the parent.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Nov 2010
    Posts
    315
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo
    Thanked 53 Times in 51 Posts

    Default Re: add pixels to qgraphicsitem

    Qt Code:
    1. class MyRect : public QObject, public QGraphicsRectItem
    2. {
    3. // all other stuff without paint method
    4. /// .....
    5.  
    6. protected:
    7. QVariant itemChange ( GraphicsItemChange change, const QVariant & value )
    8. {
    9. if (change==ItemSelectedHasChanged) {
    10. setPen(value.toBool()?mSelectedPen:mNormalPen);
    11. }
    12. return QGraphicsRectItem::itemChange(change, value);
    13. }
    14. private:
    15. QPen mSelectedPen, mNormalPen;
    16. };
    To copy to clipboard, switch view to plain text mode 

  6. #6
    Join Date
    Nov 2009
    Location
    San Antonio, TX
    Posts
    69
    Qt products
    Qt4 Qt Jambi
    Platforms
    Unix/X11 Windows
    Thanked 1 Time in 1 Post

    Default Re: add pixels to qgraphicsitem

    Probably the other way would be better. It'd be best if the "parent" had a placeholder for the "hilight item" and called some function in the item when its boundingRect() changes.
    Well thats part of my GV ignorance, how can I determine when the boundingRect changes? Is there an event? Do I override setRect?

    The child only has to reread the parent's bounding rect and adjust itself to it. If you make the child a "resizer item" (with anchors that resize the main item when you drag them) it's even simpler as the child can then control the parent without any special treatment from the parent.
    This particular item does not need to be resized, just highlighted in some manner. However, I do need the resizer option with some other items . . . and I guess the same resizer child could be used for highlighting, just ignore the anchors.

    So are there any code snippets handy to perform this task, to get me started.

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

    Default Re: add pixels to qgraphicsitem

    Quote Originally Posted by mcarter View Post
    Well thats part of my GV ignorance, how can I determine when the boundingRect changes? Is there an event? Do I override setRect?
    The item usually knows it changes its own boundingRect()
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  8. #8
    Join Date
    Nov 2009
    Location
    San Antonio, TX
    Posts
    69
    Qt products
    Qt4 Qt Jambi
    Platforms
    Unix/X11 Windows
    Thanked 1 Time in 1 Post

    Default Re: add pixels to qgraphicsitem

    The item usually knows it changes its own boundingRect()
    Well, if its based on its own rect, then not really . . . unless you override the setRect function (which is not a virtual function).


    to get the child item working, do I hide/show based on the select state in the paint method of the parent?

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

    Default Re: add pixels to qgraphicsitem

    You can call your own method that calls setRect(). setRect() won't be called behind your back, you know.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. #10
    Join Date
    Nov 2009
    Location
    San Antonio, TX
    Posts
    69
    Qt products
    Qt4 Qt Jambi
    Platforms
    Unix/X11 Windows
    Thanked 1 Time in 1 Post

    Default Re: add pixels to qgraphicsitem

    duh . . . I have control of this item . . . way too many long hours . . . thanks, wysota

    still would be interested if someone has a resizer item on hand

  11. #11
    Join Date
    Oct 2006
    Posts
    279
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows
    Thanks
    6
    Thanked 40 Times in 39 Posts

    Default Re: add pixels to qgraphicsitem

    Well, since you asked so nicely and I haven't posted anything here for ages...

    Here's an old example I managed to dig up:
    ResizeItem.h
    Qt Code:
    1. class ResizeItem : public QGraphicsItemGroup
    2. {
    3. enum Handle{None = -1, TL, T, TR, R, BR, B, BL, L, NrOfHandles};
    4. QGraphicsRectItem* handles[NrOfHandles];
    5. Handle _selectedItem;
    6. public:
    7. ResizeItem()
    8. : _selectedItem(None)
    9. {
    10. for(int i = 0;i<NrOfHandles;i++)
    11. {
    12. handles[i] = new QGraphicsRectItem(QRectF(-2,-2,5,5), this);
    13. handles[i]->setFlags(ItemIgnoresTransformations);
    14. handles[i]->setPen(Qt::NoPen);
    15. handles[i]->setBrush(Qt::black);
    16. }
    17. handles[TL]->setCursor(QCursor(Qt::SizeFDiagCursor));
    18. handles[T ]->setCursor(QCursor(Qt::SizeVerCursor));
    19. handles[TR]->setCursor(QCursor(Qt::SizeBDiagCursor));
    20. handles[R ]->setCursor(QCursor(Qt::SizeHorCursor));
    21. handles[BR]->setCursor(QCursor(Qt::SizeFDiagCursor));
    22. handles[B ]->setCursor(QCursor(Qt::SizeVerCursor));
    23. handles[BL]->setCursor(QCursor(Qt::SizeBDiagCursor));
    24. handles[L ]->setCursor(QCursor(Qt::SizeHorCursor));
    25. hide();
    26. }
    27.  
    28. protected:
    29. QVariant itemChange(GraphicsItemChange change, const QVariant &value)
    30. {
    31. if (change == ItemParentChange && scene())
    32. {
    33. QGraphicsRectItem* rectItem = qgraphicsitem_cast<QGraphicsRectItem*>(value.value<QGraphicsItem*>());
    34. if(rectItem==0){
    35. hide();
    36. return 0;
    37. }
    38. repositionChildren(rectItem->rect());
    39. show();
    40. }
    41. return QGraphicsItem::itemChange(change, value);
    42. }
    43.  
    44. void repositionChildren(QRectF rect)
    45. {
    46. handles[TL]->setPos(rect.left(), rect.top());
    47. handles[T ]->setPos(rect.center().x(), rect.top());
    48. handles[TR]->setPos(rect.right(), rect.top());
    49. handles[R ]->setPos(rect.right(), rect.center().y());
    50. handles[BR]->setPos(rect.right(), rect.bottom());
    51. handles[B ]->setPos(rect.center().x(), rect.bottom());
    52. handles[BL]->setPos(rect.left(), rect.bottom());
    53. handles[L ]->setPos(rect.left(), rect.center().y());
    54. }
    55.  
    56. void mousePressEvent ( QGraphicsSceneMouseEvent * event )
    57. {
    58. // Find out which handle was clicked
    59. int minDist = 10000000;
    60. int closestHandle = None;
    61. for(int i = 0;i<NrOfHandles;i++)
    62. {
    63. int dist = (event->pos()-handles[i]->pos()).manhattanLength();
    64. if(dist<minDist)
    65. {
    66. closestHandle = i;
    67. minDist = dist;
    68. }
    69. }
    70. _selectedItem = (Handle)closestHandle;
    71. event->accept();
    72. }
    73.  
    74. void mouseMoveEvent ( QGraphicsSceneMouseEvent * event )
    75. {
    76. QGraphicsRectItem* rectItem = qgraphicsitem_cast<QGraphicsRectItem*>(parentItem());
    77. if(rectItem==0)
    78. return;
    79.  
    80. QRectF rect = rectItem->rect();
    81. QPointF pos = event->scenePos()-scenePos();
    82.  
    83. if(_selectedItem==TR || _selectedItem==R || _selectedItem==BR)
    84. rect.setRight(qMax(rect.left(), pos.x()));
    85. else if(_selectedItem==TL || _selectedItem==L || _selectedItem==BL)
    86. rect.setLeft(qMin(rect.right(), pos.x()));
    87.  
    88. if(_selectedItem==BL || _selectedItem==B || _selectedItem==BR)
    89. rect.setBottom(qMax(rect.top(), pos.y()));
    90. else if(_selectedItem==TL || _selectedItem==T || _selectedItem==TR)
    91. rect.setTop(qMin(rect.bottom(), pos.y()));
    92.  
    93. rectItem->setRect(rect);
    94. repositionChildren(rectItem->boundingRect());
    95. }
    96.  
    97. void mouseReleaseEvent ( QGraphicsSceneMouseEvent * )
    98. {
    99. _selectedItem=None;
    100. }
    101. };
    To copy to clipboard, switch view to plain text mode 
    main.cpp
    Qt Code:
    1. #include <QtGui>
    2.  
    3. // There is one global resize item, which stays hidden most of the time.
    4. ResizeItem* resizeItem;
    5.  
    6. class RectItem : public QGraphicsRectItem
    7. {
    8. public:
    9. RectItem(QRectF rect)
    10. {
    11. setFlags(ItemIsSelectable|ItemIsMovable);
    12. setBrush((Qt::GlobalColor)((qrand()%14)+4));
    13. }
    14. QVariant itemChange(GraphicsItemChange change, const QVariant &value)
    15. {
    16. // When this item is selected, we grab the resizeItem by calling setParentItem(this)
    17. if (change == ItemSelectedChange)
    18. resizeItem->setParentItem(value.toBool() ? this : 0);
    19. return QGraphicsItem::itemChange(change, value);
    20. }
    21. };
    22.  
    23. int main(int argc, char* argv[])
    24. {
    25. QApplication app(argc, argv);
    26.  
    27. scene.setSceneRect(0, 0, 600, 600);
    28. scene.addItem(resizeItem = new ResizeItem);
    29. for(int i=0;i<50;i++)
    30. scene.addItem(new RectItem(QRectF(qrand()%500, qrand()%500, 100, 100)));
    31.  
    32. view.setScene(&scene);
    33. view.show();
    34.  
    35. return app.exec();
    36. }
    To copy to clipboard, switch view to plain text mode 

    The idea is that there is only one resize item which get's moved around whenever a rectangle is clicked. The resize item itself is invisible, but it has eight scale invariant children, which stay 5x5 pixel, regardless of view scale.

    screen.jpg

  12. The following 2 users say thank you to spud for this useful post:

    d_stranz (15th February 2011), Seishin (7th November 2012)

  13. #12
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,332
    Qt products
    Qt5
    Platforms
    Windows
    Thanks
    317
    Thanked 871 Times in 858 Posts

    Default Re: add pixels to qgraphicsitem

    Now that's a very clever example of "thinking outside the box".

  14. #13
    Join Date
    Nov 2009
    Location
    San Antonio, TX
    Posts
    69
    Qt products
    Qt4 Qt Jambi
    Platforms
    Unix/X11 Windows
    Thanked 1 Time in 1 Post

    Default Re: add pixels to qgraphicsitem

    sorry about the late response, been off working other gui issues

    spud, I appreciate the post . . . very cool
    this has helped in understanding a little more about qgraphicsview and qgraphicsitems

Similar Threads

  1. Replies: 9
    Last Post: 13th June 2012, 15:42
  2. Replies: 5
    Last Post: 23rd January 2011, 11:27
  3. QGraphicsItem mousePressEvent only on opaque pixels
    By jonks in forum Qt Programming
    Replies: 1
    Last Post: 15th February 2010, 10:24
  4. Why must I pad boundingRect() by 7 pixels
    By xenome in forum Qt Programming
    Replies: 3
    Last Post: 10th September 2009, 14:07
  5. Pixels
    By Dante in forum Qt Programming
    Replies: 1
    Last Post: 21st April 2009, 20:50

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
  •  
Qt is a trademark of The Qt Company.