Results 1 to 11 of 11

Thread: Qt 4.6 GraphicsView items remove problem

  1. #1
    Join Date
    Sep 2009
    Posts
    31
    Thanks
    2
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Unhappy Qt 4.6 GraphicsView items remove problem

    Hi,
    I've some strange problem with Qt 4.6.2. I spent long time with trying to fix it, but at the end i only downgrade to Qt 4.5.3, where my application is functional.

    Problem is, that when I remove my own item from QGraphicsScene, sometimes it still remains on scene. It's not anymore clickable, but it's realy on scene, no update() or repaint helps. It seems, that problem occures only when I'm adding items using parser (so probably too quickly).

    Isn't there any new flag in Qt 4.6? I have had first problem with items didn't send geometry changes, but setFlag(ItemSendsGeometryChanges); was what I need.

    But now I realy don't know, where could be problem. When I use Qt 4.5.3, application works properly. Could it be caused by some optimalization changes?

    Thanks for any answers.

  2. #2
    Join Date
    Sep 2009
    Posts
    31
    Thanks
    2
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt 4.6 GraphicsView items remove problem

    I did some measurement a I found this:
    I've small example with about 18 graphics items on scene. When I use QGraphicsScene::items().count and it returns 18. I can remove 2 of them a than the same method returns correctly 16. But there is still removed items displayed on scene.

    However, if found the way how to update it to display items correctly:
    I have to change QGraphicsScene::sceneRect() and than upate scene. So if I want to get properly functionality, i have to call QGraphicsScene::setSceneRect(...) and set sceneRect e.g to scene()->sceneRect().adjusted(1,1,1,1) and then revert it and finally call scene()->update(); and whole scene is then painted correctly.
    So I thing if there could be some cached content in scene or in view?

    Any ideas?
    Thanks.

  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: Qt 4.6 GraphicsView items remove problem

    Please show us the implementation of your custom items. paint() and boundingRect() are the most interesting routines.
    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.


  4. #4
    Join Date
    Sep 2009
    Posts
    31
    Thanks
    2
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt 4.6 GraphicsView items remove problem

    Ok, here is sample of my code:

    paint method:
    Qt Code:
    1. void TransitionArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
    2. {
    3. if (startPoint == endPoint) return;
    4.  
    5. QColor lineC;
    6. Qt::PenStyle lineS;
    7. float lineWidth;
    8. float edgeLineWidth_e = editor->edgeLineWidth*TR_LINE_VIEW_COEF; // better looking on scene
    9.  
    10. if (dimmed){
    11. lineWidth = edgeLineWidth_e * dimEdgeLineCoef;
    12. lineS = dimEdgeLineStyle;
    13. lineC = dimEdgeLineColor;
    14. } else{
    15. lineWidth = edgeLineWidth_e * edgeLineWidth;
    16. lineS = edgeLineStyle;
    17. lineC = edgeLineColor;
    18. }
    19.  
    20. if (checked){
    21. painter->setPen(QPen(QColor(255,100,100), lineWidth, lineS));
    22. }
    23. else{
    24. painter->setPen(QPen(lineC, lineWidth, lineS));
    25. }
    26.  
    27. painter->setBrush(Qt::NoBrush);
    28. // p is clasls variable QPainterPath, updated in adjust method, which is called when
    29. // changed (position or size) -> this works correctly
    30. painter->strokePath(p, painter->pen());
    31.  
    32. // draw arrow
    33. if (checked)
    34. painter->setBrush(QColor(255,100,100));
    35. else
    36. painter->setBrush(lineC);
    37.  
    38. painter->drawPolygon(pa); // coumputed in adjust
    39. }
    To copy to clipboard, switch view to plain text mode 
    boundingRect metohod is implemented in superclass as virtual
    Qt Code:
    1. QRectF Transition::boundingRect() const
    2. {
    3. QPolygonF areaPol = makeClickArea(p); // p is clasls variable QPainterPath
    4.  
    5. QRectF rect = areaPol.boundingRect();
    6.  
    7. if (label)
    8. rect |= (mapFromItem(label, label->boundingRect())).boundingRect(); // rect over pathRect and labelRect
    9.  
    10. for (TLabelXList::ConstIterator labelIt = nextLabels.begin();
    11. labelIt != nextLabels.end();
    12. ++labelIt)
    13. {
    14. rect |= (mapFromItem((*labelIt), (*labelIt)->boundingRect())).boundingRect();
    15. }
    16.  
    17. rect |= pa.boundingRect();
    18.  
    19. return rect;
    20. }
    To copy to clipboard, switch view to plain text mode 
    and finally my shape() method:
    Qt Code:
    1. QPainterPath Transition::shape() const
    2. {
    3. QPainterPath path;
    4.  
    5. QPolygonF areaPol = makeClickArea(p);
    6.  
    7. areaPol = areaPol.united(pa);
    8.  
    9. if (label != NULL)
    10. areaPol = areaPol.united(mapFromItem(label, label->boundingRect()));
    11.  
    12. for (TLabelXList::ConstIterator labelIt = nextLabels.begin();
    13. labelIt != nextLabels.end();
    14. ++labelIt)
    15. {
    16. areaPol = areaPol.united(mapFromItem((*labelIt), (*labelIt)->boundingRect()));
    17. }
    18.  
    19. path.addPolygon(areaPol);
    20.  
    21. return path;
    22. }
    To copy to clipboard, switch view to plain text mode 

    In attachements are sample images of my application:
    - blue and green polygons are only for my testing, blue == shape polygon and green == bounding rect of item -> green is only for TransitionArc
    - note: i create my own shape polygon bigger then line/curve only for make clicking on it easier (is it possible to do it simplier?)
    - sample.png is state when I loaded automata
    - sample_wrong.png is state after I deleted state 2 and move with state 1. Right Arc is still repainted even if I move with state 1 over it. But in Qt 4.5.3 I have no problem.
    Attached Images Attached Images

  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: Qt 4.6 GraphicsView items remove problem

    Are you sure you are always painting only inside the boundingRect() for each and every of your items? Does the boundingRect() ever change (return a different value than earlier)? Do you notify the architecture about such changes?
    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.


  6. #6
    Join Date
    Sep 2009
    Posts
    31
    Thanks
    2
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt 4.6 GraphicsView items remove problem

    Thanks for reply, but I'm affraid that I'm not realy understand.
    I'm sure about painting ever inside bounding rect - it has been reason why I have done my testing polygons(green).
    But what do you mean with boiundingRect() -> ever change? I thought that boundingRect() is called automaticly from graphicsView and since it is computed from my internal variables, it should be ever alright?
    So I thing, that I'm ever change boudningRect and shape when I move or change some item on scene, it should be enough? Or not?

    But I think about what you have written and I tried some change. In my adjust method. I had called update() at its end before my change:
    Qt Code:
    1. void adjust()
    2. {
    3. // some changed with my path variable
    4. ...
    5. update();
    6. }
    To copy to clipboard, switch view to plain text mode 

    and now I have tried this:
    Qt Code:
    1. void adjust()
    2. {
    3. prepareGeometryChanges();
    4. ...
    5. // some changes on my path variable
    6. // no update() method called
    7. }
    To copy to clipboard, switch view to plain text mode 
    And I'm realy surprised, because it is functional. Could you please try to explain it to me? Is there any important difference? (I thought that prepareGeometryChange only causes update when it's necessary).
    What's implementation of prepareGeometryChanges? .. Does it create some local object which do some comparation in its destructor?
    Last edited by Piskvorkar; 9th March 2010 at 20:26.

  7. #7
    Join Date
    Sep 2009
    Posts
    31
    Thanks
    2
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt 4.6 GraphicsView items remove problem

    I addition i would like to counterpoint, that when I was using Qt 4.5.3, everything was ok. So there has to be some important behavior change in Qt 4.6. Isn't here some different scene updating? I suppose that now when I call prepareGeometryChange() I will inform environment about change in most cases then before, but why update() doesn't it too?

  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: Qt 4.6 GraphicsView items remove problem

    Quote Originally Posted by Piskvorkar View Post
    I'm sure about painting ever inside bounding rect - it has been reason why I have done my testing polygons(green).
    I can see the polygons for the arcs only.

    But what do you mean with boiundingRect() -> ever change? I thought that boundingRect() is called automaticly from graphicsView and since it is computed from my internal variables, it should be ever alright?
    Graphics View won't requery your item for its boundingRect() unless you specifically tell it that it has changed. So if at some point your boundingRect() implementation was to return a different value than it did a second earlier, you are obligated to tell GV about it by calling your item's QGraphicsItem::prepareGeometryChange() method.


    And I'm realy surprised, because it is functional. Could you please try to explain it to me?
    I think I just did
    What's implementation of prepareGeometryChanges? .. Does it create some local object which do some comparation in its destructor?
    Qt is Open Source - just dive into the sources and see for yourself.

    Quote Originally Posted by Piskvorkar View Post
    I addition i would like to counterpoint, that when I was using Qt 4.5.3, everything was ok.
    This doesn't mean anything. If you are abusing the architecture by doing some things that were never meant to happen you can't expect it to work in future releases.

    So there has to be some important behavior change in Qt 4.6.
    Even more than one... That's why the version numbering changed from 4.5.x to 4.6.x 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.


  9. The following user says thank you to wysota for this useful post:

    Piskvorkar (10th March 2010)

  10. #9
    Join Date
    Sep 2009
    Posts
    31
    Thanks
    2
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt 4.6 GraphicsView items remove problem

    Thanks very much!
    But I still don't understend, why update() doesn't notifiy GV about my changes. I used update() before (in my adjust method - only method when I'm doing items changes) and so I thought, that I'm notifying GV about changes. But in Qt 4.6 it's not right more. However in documentation for QGraphicsItem is still written:
    Schedules a redraw of the area covered by rect in this item. You can call this function whenever your item needs to be redrawn, such as if it changes appearance or size. ....
    If the only thing prepareGeometryChanges() does is calling update if necessarey, why I can't use update() instead? It was the reason I've called update() at the end of my adjust() method, to be sure that it will be called ever - maybe not good for performance ...

    But I've just read this for QGraphicsItem::boundingRect():
    f you want to change the item's bounding rectangle, you must first call prepareGeometryChange().
    So I'm quite confused from it :-). Does update() need any other methods called before itsefl in order to GV realy update item on scene?

    It's not so important since it's functionaly for me, but I'm interesting about it.
    Once more thanks for replies!

  11. #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: Qt 4.6 GraphicsView items remove problem

    Quote Originally Posted by Piskvorkar View Post
    But I still don't understend, why update() doesn't notifiy GV about my changes.
    If it did, the scene would have to rebuild all its internal structures for every item every time it repainted itself. update() only says "hey, repaint me".

    I used update() before (in my adjust method - only method when I'm doing items changes) and so I thought, that I'm notifying GV about changes.
    Only about changes to the looks of the item but not to the size of it.
    But in Qt 4.6 it's not right more.
    It has never been.
    If the only thing prepareGeometryChanges() does is calling update if necessarey
    That's not true. The docs say that a redraw is scheduled as part of the method, they don't say it is the only thing that is done there.

    why I can't use update() instead?
    Laziness is not an excuse, taking even a brief look at the source code of the method may be enlightening.

    Qt Code:
    1. void QGraphicsItem::prepareGeometryChange()
    2. {
    3. if (d_ptr->inDestructor)
    4. return;
    5. if (d_ptr->scene) {
    6. d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true;
    7. d_ptr->geometryChanged = 1;
    8. d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
    9. d_ptr->notifyBoundingRectChanged = !d_ptr->inSetPosHelper;
    10.  
    11. QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
    12. scenePrivate->index->prepareBoundingRectChange(this);
    13. scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true, /*force=*/false,
    14. /*ignoreOpacity=*/ false, /*removingItemFromScene=*/ false,
    15. /*updateBoundingRect=*/true);
    16.  
    17. // For compatibility reasons, we have to update the item's old geometry
    18. // if someone is connected to the changed signal or the scene has no views.
    19. // Note that this has to be done *after* markDirty to ensure that
    20. // _q_processDirtyItems is called before _q_emitUpdated.
    21. if (scenePrivate->isSignalConnected(scenePrivate->changedSignalIndex)
    22. || scenePrivate->views.isEmpty()) {
    23. if (d_ptr->hasTranslateOnlySceneTransform()) {
    24. d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(),
    25. d_ptr->sceneTransform.dy()));
    26. } else {
    27. d_ptr->scene->update(d_ptr->sceneTransform.mapRect(boundingRect()));
    28. }
    29. }
    30. }
    31.  
    32. d_ptr->markParentDirty(/*updateBoundingRect=*/true);
    33. }
    To copy to clipboard, switch view to plain text mode 
    As you see it does something more than just calling update().

    It was the reason I've called update() at the end of my adjust() method, to be sure that it will be called ever - maybe not good for performance ...
    That's ok but it's not sufficient when your item changes its size.

    Does update() need any other methods called before itsefl in order to GV realy update item on scene?
    Please understand, when boundingRect() changes, it is not enough to update the area that used to be covered by the previous boundingRect(). You have to update both the old boundingRect() and the new one, right? So you need to tell GV about such situation so that it can rebuild its internal index and update both areas. Otherwise you'll have artifacts on the view.
    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.


  12. The following user says thank you to wysota for this useful post:

    Piskvorkar (10th March 2010)

  13. #11
    Join Date
    Sep 2009
    Posts
    31
    Thanks
    2
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Qt 4.6 GraphicsView items remove problem

    Ok, I think I'm begining to understand :-). Believe that I've realy looked at the prepareGeometryChange code, but I have to confess I was realy lazy to try to apprehend it. It's my unluckiness, that my defective code worked properly under Qt 4.5.3, but now I think it should be ok. Realy thanks much for clarification.
    I suppose that what prepareGeometryChange does (among others) is that it set some flags which are affected in next event loop so boundingRect and update and any others methods needed to completly renewing are called.

Similar Threads

  1. Remove Legend items, move legends
    By giusepped in forum Qwt
    Replies: 0
    Last Post: 11th February 2009, 02:35
  2. graphicsview Problem
    By tampstaffs in forum Qt Programming
    Replies: 6
    Last Post: 8th February 2009, 19:59
  3. Light items for the graphicsView
    By maverick_pol in forum Qt Programming
    Replies: 12
    Last Post: 1st November 2007, 18:51
  4. Zoom GraphicsView but not Items
    By abbapatris in forum Qt Programming
    Replies: 2
    Last Post: 15th October 2007, 19:47
  5. Replies: 1
    Last Post: 24th August 2006, 11:44

Tags for this Thread

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.