Reputation: 47
I want to undo or redo actions in a QGraphicsScene
that is linked to a QGraphicsView
: For that, I use QGraphicsEllipse
(to draw points while moving and clicking on the QGraphicsView
) in my mouseMoveEvent
method, I push every QGraphicsEllipse
in a QVector<QGraphicsItem>
, and when the QAction
"undo" is triggered the program must delete the last ellipses (determined number of ellipses) drawn in my QGraphicsView
thanks to my QGraphicsScene
.
When I clear my QGraphicsScene
and try to add all QGraphicsItems
that were pushed in my QVector<QGraphicsItem>
, I got an error: my app goes down!
if(index < historyIndex.size()){
for (int i = 0; i < scHistory.size() - historyIndex[index]; i++){
scene->addItem((QGraphicsItem*)scHistory[i]);
}
index++;
}
QVector<QGraphicsItem *> scHistory;
Upvotes: 2
Views: 527
Reputation: 11575
QGraphicsScene::addItem
takes the ownership of the element added, check the doc. It means that it is now in charge of destructing the element, which happens when you clear the scene with QGraphicsScene::clear
. From that point on, your vector is full of dangling pointers.
One quick fix is to replace the call to QGraphicsScene::clear
with a manual removal of items through QGraphicsScene::removeItem
, which doesn't destroy the item (it returns the ownership to the caller). Then, destroy only those elements that are actually out of the scene, and add back the rest. Another option, more efficient, is to remove only the elements you need, keeping the rest, so you also increase performance by avoiding add back a large number of items from the history.
Without a full knowledge of your code, the second options may be something like:
if(_indexHistoryRoam < _indexHistory.size()){
// Remove only items beyond history
const int range = _sceneHistory.size() - _indexHistory[_indexHistoryRoam];
for (int i = range; i < _sceneHistory.size(); i++){
scene->removeItem((QGraphicsItem*)_sceneHistory[i]);
delete _sceneHistory[i]; // item must be destroyed to avoid a leak
}
_indexHistoryRoam++;
} else { // force removal of all elements
scene->clear();
}
scene->update();
Upvotes: 2