PDA

View Full Version : Clearing GraphisScene causes SIGSEGV



Lord_Navro
24th November 2012, 13:28
Hi,

I have a custom QGraphicsscene like this



class DisjointSetsScene : public QGraphicsScene
{
Q_OBJECT
public:

//...

DisjointSetsScene(QObject *parent, /* ... */);
//...

signals:
void signalNodeClicked(Node *node);
// ...
};


with some constructor


DisjointSetsScene::DisjointSetsScene(QObject *parent, /* ... */)
: QGraphicsScene(parent)


I'm adding some custom graphics items and lines like this


NodeItem *nodeItem = new NodeItem();
nodeItem->setRect(startCoords.x(), startCoords.y(), 30, 30);
nodeItem->setBrush(nodeBrush);
nodeItem->setPen(nodePen);
//...
addLine(startCoords.x() + 15, startCoords.y() + 15, endCoords.x() + 15, endCoords.y() + 15, arrowPen);
//...
addItem(nodeItem);


Now, at some point (when a node is clicked), i need to repaint the whole scene. So i want to clear it first, however, this thing


qDeleteAll(items());

gives me SIGSEGV. Any suggestions?

amleto
24th November 2012, 13:49
why do you want to delete everything just because you want to repaint? crazy.

And if you want to delete the items, then you will probably need to remove() them from the scene first!

Lord_Navro
24th November 2012, 16:04
Hi,
thank you for your answer.

As for deleting everything -> i didn't express myself clearly enough. I need to move nearly all the objects and delete some of them. Therefore its a lot easier to "rebuild" the whole scene with new objects. I'm aware of the overhead, but optimalization is not an issue now.

Searching web i found this function (slot) http://doc.qt.digia.com/qt/qgraphicsscene.html#clear
The problem, however, remains the same.

To be more specific, I have a forest graph which i'm trying to display and manipulate. I have a "add new tree to the forest" slot connected to a button which triggers this action:


forest->append(new Node(NULL, "new root node"));
scene->resetScene();

This works fine, the scene is changed correctly.

Further, I have a signal being emited from each "NodeItem" on the scene whenever it's clicked (the "node" passed in the signal is a pointer into the data structure representing my forest):



void NodeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
emit signalNodeClicked(node);
}


The signal is passed to the main window, where a method is called based on the current tool selected


void MainWindow::slotNodeClicked(Node *node)
{
currentTool->nodeClicked(node);
}

and this action is processed:


void AddNodeTool::nodeClicked(Node *node)
{
Node *newNode = new Node(node, "child");
node->children.append(newNode);
scene->resetScene(); //this calls the clear() method and causes segmentation fault
}


My suggestion was that it can be problem that the object that emits the original signal (instance of NodeItem, which is a subclass of QGraphicsEllipseItem) gets deleted in the clear() method...however, when I commented the call to clear(), SIGSEGV moved just one line further to


foreach(Node* tree, *forest)
{
coords = addNodeItemToScene(tree, coords);
coords.setY(0);
}


Finally, when I comment the problematic scene->resetScene(); line mentioned above and call it later via the slot in the first code snippet in this message (which btw also adds new tree to the forest), all works fine and the scene is rebuild correctly with new nodes added.....

amleto
24th November 2012, 16:16
I'm not going to try and decipher 50% story and 50% code. Check your destructors (incidentally you haven't shown any of that code...).

read my sig.

Lord_Navro
24th November 2012, 18:12
This is my complete project: https://github.com/LordNavro/DisjointSets I dont have destructors as I dont need any by now. Thanks for any suggestion.

norobro
24th November 2012, 19:40
I just took a quick peek at your code. In createTools(void) you are using an unitialized pointer to the scene. See if changing the the order of the statements in the mainwindow constructor helps:
forest = new QList<Node *>;

/* createActions();
createMenus();
createToolBars();
createTools();
*/
QBrush brush(Qt::green);
QPen pen(Qt::yellow);
scene = new DisjointSetsScene(this, forest, DisjointSetsScene::TREE, pen, brush, pen);
connect(scene, SIGNAL(signalNodeClicked(Node*)), this, SLOT(slotNodeClicked(Node*)));
view = new QGraphicsView(scene, this);

createActions();
createMenus();
createToolBars();
createTools();

this->setCentralWidget(view);

Lord_Navro
24th November 2012, 20:33
I'm so stupid. I'm so stupid. I'm so stupid. I'm so stupid.

God bless you, norobro.