Search code examples
c++qtqgraphicsviewqgraphicsscene

QGraphicsItems can only be created on the heap?


In the constructor of a QMainWindow...

A new circle is created on the heap and passed to the scene, the circle shows up, everythin is working:

    QGraphicsScene * scene = new QGraphicsScene(this);
    CustomGraphicsView * view = new CustomGraphicsView(scene,this);

    QGraphicsEllipseItem * ellipse = new QGraphicsEllipseItem (100,100,30,30);
    ellipse->setPen(QPen(Qt::green,10));

    scene->addItem(ellipse);

Now we create circle on the stack and pass it by reference. But this time the cricle will never shows up:

QGraphicsScene * scene = new QGraphicsScene(this);
CustomGraphicsView * view = new CustomGraphicsView(scene,this);

QGraphicsEllipseItem ellipse(100,100,30,30);
ellipse.setPen(QPen(Qt::green,10));

scene->addItem(&ellipse);

I guess it gets destroyed before it shows up. But I don't understand why? Why is this not working and what is the rule behind this behaviour?


Solution

  • QGraphicsEllipseItem * ellipse = new QGraphicsEllipseItem (100,100,30,30);
    ellipse->setPen(QPen(Qt::green,10));
    
    scene->addItem(ellipse);
    

    This works because the scene object is in charge of deleteing the object which you've allocated via new. Somewhere in the depths of the Qt framework, there will be a call along the lines of:

    delete item;
    

    Now with this code:

    QGraphicsEllipseItem ellipse(100,100,30,30);
    ellipse.setPen(QPen(Qt::green,10));
    
    scene->addItem(&ellipse);
    

    Consider what happens. The delete item; is still there, but it will be applied not only on a pointer to a local object but (probably, depending on the program flow) also to a pointer to an object which no longer lives. The code which performs the delete simply has no idea that the object was not created via new.

    Any attempt to destroy an object more than once is undefined behaviour, as is trying to use an object which was already destroyed. Your question is a good example of why passing around pointers to local objects should be treated as an especially dangerous action which requires extra caution.

    By the way:

    But this time the cricle will never shows up:

    That's a mere coincidence. Undefined behaviour means that everything can happen.