QCustomPlot Discussion and Comments

QCPItemRect setParent crashReturn to overview

Hi,

I am creating new QCPItemRect and then make some graph its parent. So that when I call removeGraph, all QCPItemRects will disappear also. It works great.

But the problem comes when I remove qcustomplot object. Then my program crashes and I get error:
pure virtual method called
terminate called without an active exception

Any idea how to fix this?

QCustomPlot *w = new QCustomPlot(this);
...
...
QCPItemRect *rect = new QCPItemRect(w);
rect->setParent(w->graph(graph_int));
...
...

void MainWindow::customplot_remove_plot()
{
...
w->clearGraphs();
w->deleteLater();
...

I think
the item's parent must be a QCustomPlot-widget
http://www.qcustomplot.com/documentation/classQCPAbstractItem.html#a9922507d8b4503a1fe1ed0b1030e23b6

QCustomPlot has in itself a container of pointers. When QCustomPlot-object is destroyed, then destructors of all items in container are called.

QCustomPlot::~QCustomPlot()
{
//...
  clearItems();
//...
}

int QCustomPlot::clearItems()
{
  int c = mItems.size();
  for (int i=c-1; i >= 0; --i)
    removeItem(mItems[i]);
  return c;
}

bool QCustomPlot::removeItem(QCPAbstractItem *item)
{
  if (mItems.contains(item))
  {
    delete item;
    mItems.removeOne(item);
    return true;
  } 
//...
}

That is, if you have already deleted the items yourself, then the container contains a broken pointer, and operator delete is called for the broken pointer.

The correct way to delete an item:

 removeItem(item);

I actually solved this with layer and. I put every item on additional layer and set the layer name to graph as dynamic property.

removeItem code:

        
            QString str_layer = w->graph(graph_name.toInt())->property("layer_name").toString();
            QCPLayer * layer = findChild<QCPLayer *>(str_layer);
          
            if (layer) { //if we have layer, remove all items 
                foreach (QCPLayerable* l, layer->children()) {
                    if (qobject_cast<QCPAbstractItem*>(l)){
                        w->removeItem((QCPAbstractItem*)l); 
                    }
                }
            
            w->removeLayer(layer); //and remove layer
        }