A. Vieira A. Vieira - 2 months ago 56
C++ Question

How to repaint a QChart

I'd like to know how to repaint a

after I append new points to the
added to it.

The goal is to use this for displaying data being acquired at high rates (up to 400 000 pts/sec) and updating the plot as the points arrive in packets.

Here's the test program I've been working on:


class MainWindow : public QMainWindow{

QLineSeries *series;
QChart *chart;
QChartView *chartView;

int cnt=0;

explicit MainWindow(QWidget *parent = 0);

private slots:
void on_pB_Start_clicked();

Ui::MainWindow *ui;

MainWindow constructor:

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){

series = new QLineSeries();

chart = new QChart();


// A bunch of formatting
chartView = new QChartView(chart);


And a pushButton
event to add points to the series:

void MainWindow::on_pB_Start_clicked(){
// Update plot here << ======== HOW?

The OpenGLSeries example does it somehow. I don't understand how. But that case it's a bit different as it replaces all points in the series with new ones, instead of appending them.


First, if your will receive and append points at 400000 pts/sec in GUI thread, your application will get absolutely freezed. So you need to dedicate another thread to data receiving and processing, and send processed graphics data to the GUI thread using (for example) signals/slots connected with QueuedConnection. By "processing" I mean at least some sort of decimation (averaging, dropping, decimation as those DSP guys understand it), because 400000 pts/sec seems to fast, you'll waste your memory and GUI performance. But if you do not want to decimate, it's up to you. In this case you may consider a more lightweight data delivery mechanism than QueuedConnectioned signals/slots.

The second question is when to plot? Not so long ago I implemented similar functionality with QCustomPlot at much lower rates. The main problem I faced was a huge (and varying) lag when I tried to replot after receiving each point, especially while plotting antialiased graph. In your case the solution is to subclass QChartView (I suppose you have already done it), override timerEvent in it and call startTimer()/killTimer() when you need to start/stop replotting. Alternatively, you may hold a timer in an object which owns the QChartView object and issue replotting from there, but it looks like abstraction leakage in comparison to subclassing QChartView. All in all, this approach allows you to achieve almost constant framerate and make it as smooth as you want without freezing application's interface.

And finally, how to replot? QChartView seems to have repaint() method inherited from QWidget which does what you need.