Reputation: 98
I am using QChart for an application. The application need to show some data realtime. There will be one chart and 24 series in the chart. The data rate is 400pts for every channel.
I used another thread for receiving and processing received data and emit the processed data to a slot for append datas to update the chart series.
I refered to https://doc.qt.io/qt-5/qtcharts-audio-example.html. In my case, each series is limited to 2000 points, if the number of points in the series is less than 2000, add the new point to the series, if the number of points in the seried is more than 2000, delete first point, move the rest of datas to left and add the new point in the end. This will make the chart look like move from right to left.
For good performance, I also used series->replace()
and series->setUseOpenGL(true)
.
My problem is that the application will get freezed soon when it started. I tried delete the codes of update the chart, everything looked fine. Could anyone help me how to improve the performance of update the chart?
Thanks!
Upvotes: 5
Views: 5620
Reputation: 3
You can try getting the list of current points from the series, and then make the updates (appending, removing the first point, and shifting the points' x-axis coordinates) on the list.
You then do a replace on the series with the updated list of points.
auto m_series0 = new QLineSeries;
QList<QPointF> points = m_series0->points();
// make "expensive updates" on points
m_series0->replace(points); // update series with new points
Upvotes: 0
Reputation: 3855
I have the same problem. The main problem I think is, that QLineSeries
sends the signal pointAdded()
and triggers a repaint. Additionally append()
and remove
are performance sinks. QtChart does only support QList
and no form of a ring buffer as far as I know.
I tried the way putting new data into a QQueue<QPointsF>
and copy the data within a timer hanler set to 20 Hz. To avoid updating I disable these:
void
MyGraph::handle_timer_timeout()
{
_chartView->setUpdatesEnabled(false);
// _chart->removeSeries(_series);
while(_buf->count()>0){
_series->append(_buf->dequeue());
_series->remove(0);
}
// _chart->addSeries(_series);
_axisX->setRange( _series->at(0).x(),
_series->at(_seriesSize-1).x());
_axisY->setRange(-1,1);
_chartView->setUpdatesEnabled(true);
}
This results in roughly 20-30% less processor usage.
I also found the hint that temporary removing the series (removeSeries()
,addseries()
) can result in some improvements but I can't confirm that.
This may be better but not really good enough. I hope someone finds a better solution.
or use QLineSeries::replace()
. For that I use a double buffer QVector<QVector<QPointF>> *_lists
:
void
MyGraph::handle_timer_timeout()
{
_chartView->setUpdatesEnabled(false);
auto listsother = (_listsCrurrent+1)%2;
auto bufcnt = _buf->count();
//
QVector<QPointF> *newData = &_lists->data()[listsother];
int idx;
for(idx=0; idx<_seriesSize-bufcnt;idx++){
newData->replace(
idx,
_lists->at(_listsCrurrent).at(idx+bufcnt));
}
for(; idx<_seriesSize;idx++){
newData->replace(
idx,
_buf->dequeue());
}
_listsCrurrent = listsother;
_series->replace(_lists->at(_listsCrurrent));
_axisX->setRange( _series->at(0).x(),
_series->at(_seriesSize-1).x());
_axisY->setRange(-1,1);
_chartView->setUpdatesEnabled(true);
}
This is more performant on my computer.
Alternatively you can take a look on QWT.
Upvotes: 2