So i am using QCP to liveplot some sensor data, which worked like a charm when i ran a loop within the liveplot class plotting some random values to see if it works. Now that i started splitting everything up into threads and feeding some real data into the plot.
The thread to display the data works quite simple:
void LivePlot::paint(QPainter* painter) { if (CustomPlot_) { QPixmap picture(boundingRect().size().toSize()); QCPPainter qcpPainter(&picture); CustomPlot_->toPainter(&qcpPainter); painter->drawPixmap(QPoint(), picture); } } void LivePlot::drawVal(double val_pair) { static double tsp = 0; CustomPlot_->graph(0)->addData(tsp, val_pair); CustomPlot_->yAxis->setRange(val_pair - 10, val_pair + 10); if(tsp>200) CustomPlot_->xAxis->setRange(tsp - 200, tsp + 200); CustomPlot_->replot(); tsp++; } void LivePlot::listenDataStream() { static double old = 0; while (DataStream.running()) { if (value != old) { drawVal(value); old = value; } } } void LivePlot::startDataListener() { std::thread* refresh_thread_ = new std::thread([this]{listenDataStream();}); refresh_thread_->detach(); }
Feeding data into the object looks like so (displaying the data doesnt need to be 100% correct, skipping a few values is fine hence just changing a member in the liveplot object is fine (would appreciate any tips on how to solve this more elegant though). Also here im just working with a dummy dataset emulating the sensor, doesnt really make any difference to pulling real data):
std::list<double>* lyst = new std::list<double>; for (size_t i = 0; i < mmhg->size(); i++) { QTime dieTime= QTime::currentTime().addMSecs(10); lyst->push_back(mmhg->at(i)); // algorithm here filtering sample and detecting peaks within // a moving window, no problem here since removing it // yields the same error liveplot_->value = filtered_val; while (QTime::currentTime() < dieTime){} }
After debugging for quite some time the backtrace seems to look like this most of the time:
ASSERT failure in QVector<T>::at: "index out of range", file C:\Qt\5.15.1\mingw81_64\include/QtCore/qvector.h, line 455 Depth Function 5 QVector<double>::at 6 QCPGrid::drawGridLines 7 QCPGrid::draw 8 QCPLayer::draw 9 QCustomPlot::draw 10 QCustomPlot::toPainter 11 LivePlot::paint 12 QSGDefaultPainterNode::paint() 13 QSGDefaultPainterNode::update() . . .
The code section in qcustomplot.cpp starting line 7333 looks like so :
for (int i=0; i<tickCount; ++i) { if (i == zeroLineIndex) continue; // don't draw a gridline on top of the zeroline t = mParentAxis->coordToPixel(mParentAxis->mTickVector.at(i)); // y painter->drawLine(QLineF(mParentAxis->mAxisRect->left(), t, mParentAxis->mAxisRect->right(), t)); }
Even checking if the index exists if (i < mParentAxis->coordToPixel(mParentAxis->mTickVector.size()))
before accessing it will crash at access.
The error doesnt come up at the same time everytime, however it comes up everytime, sooner or later.
Would greatly appreciate any help/tips for any workarounds