Why does removeItem() + delete cause QGraphicsView to crush whereas delete doesn't?
-
I am creating the custom scene for QGraphicsView with items derived from QGraphicsViewGroup:
@class QI_DiagramInteraction: public QGraphicsItemGroup
{
public:
...
std::weak_ptr<QI_ObjectSchemaElement> params;
...
}@Here QI_ObjectSchemaElement is custom shared data model element which defines the appearance and position of the item. Presently, the group is empty (I will add some QGraphicsRectItem elements into it in the future). The item functionality is realized by reimplementing the following QGraphicsViewGroup methods:
@boundingRect ();
shape();
paint();
@All three methods load the necessary data exclusively from the associated params object. When the data in params object are altered I force the updating of the scene by calling:
@removeItem(it2->second);
it2->second->show(); //I added this line because some of the items may be hidden at the removal time
addItem(it2->second);@Everything works fine until I try to remove the items. I have read in the documentation that the preferable way to do it is to call removeItem() and then call delete (I also want to do it in two steps to reuse some of the items). I have no problems if the underlying params object did not change during the lifetime of QI_DiagramInteraction item. However, if some changes did take place I get the access violation error (but not immediately after deleteon) at the line 235 of qcoreapplication.h:
@inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
{
if (event) event->spont = true; return self ? self->notifyInternal(receiver, event) : false; // ERROR HERE!
}@
This indicates that the program tries to access the item instance after it had been deleted. Indeed, no error observed when I keep all the once created items.At first glance, the reason might be in wrong usage of signal-slot mechanism, so that some queued signal calls the deleted object. To check this guess I tried to collect the removed items into std::stack<QI_ObjectSchemaElement*> and delete them after reasonable delay but found that the same error still persists. Most surprisingly, everything started to work flawless when I changed the code to remove items by direct call of delete everywhere instead of invoking the removeItem() function. It seems that error after calling the removeItem occurs when QGraphicsView needs to repaint the region where the deleted item was located before changing the params pointer (even if it was actually correctly redrawn in the new position many times before actual removing and deletion). I also checked that no errors are generated in overwritten functions listed above.
Can you, please, help me understand this error and the way to avoid it?
-
Hi and welcome to devnet,
Can you setup a minimal compilable example that shows this behavior ?
Also, what Qt/OS combo are you using ?
-
I am using Qt 5.2.0 (Windows 8, Microsoft Visual C++ compiler 11.00 (x86)). I will try to setup the minimal example.
-
Hi!
I have a similar problem. I create a QGraphicsItemGroup and push QGraphicItem's. Some time later I try to rebuild that group: first thing I do is delete previous. It looks like this:
@
void MapScene::RebuildGrid()
{
removeItem(m_pGrid); // <--- here is the problem
delete m_pGrid;qreal fScale = m_pBackgoundItem->scale(); qreal w = m_pBackgoundItem->boundingRect().right()*fScale; qreal h = m_pBackgoundItem->boundingRect().bottom()*fScale; m_pGrid = new QGraphicsItemGroup; for (int i = 0; i<w; i+=m_iCellGridSize) { QLine vline(i, 0, i, h); QGraphicsLineItem* pvGLI = new QGraphicsLineItem(vline); pvGLI->setZValue(2.0); m_pGrid->addToGroup(pvGLI); for (int j = 0; j<h; j+=m_iCellGridSize) { QLine hline(0, j, w, j); QGraphicsLineItem* phGLI = new QGraphicsLineItem(hline); phGLI->setZValue(2.0); m_pGrid->addToGroup(phGLI); } } addItem(m_pGrid);
}
@So removeItem is crashing. I tried to remove this line, however it's crashing after delete too. What could be wrong ?
Thank you. -
I found a problem.. I did clear the scene and then tried to delete an Item from the already cleared scene. So I think you should add some kind of comparison if the item exists before deleting and if it isn't show some kind of warning.
-
Pavel, I always make the checks you have suggested, so the my problem is caused by something else. I still did not figure out its reason. I found that usually it is NOT caused by items which are actually have been removed and deleted. However, recently I fixed bug in constructors of few of my graphicsItem objects (also not ones which I am actually removing and deleting) derived from multiple classes: i did not call the proper constructor for one of the base classes. I did not check, however, if this fixed the removeItem() issue. As an ad-hoc solution, I avoid using removeItem() in the code, and everything works fine.