Search code examples
c++qtqt5qchart

QChart not displaying any series data when using QDateTimeAxis


I want to display a real-time plot using QChart and QLineSeries where X values are timestamps. Everything works as expected when I use QValueAxis for X axis, but switching to QDateTimeAxis results in no data being plotted - just an empty chart.

Sample code that demonstrates the problem:

QLineSeries *series = new QLineSeries();
series->setUseOpenGL(true); // Disabling OpenGL doesn't change anything.

QChart *chart = new QChart();
chart->addSeries(series);

QValueAxis *axisY = new QValueAxis();
axisY->setTickCount(5);
axisY->setMinorTickCount(1);
axisY->setLabelFormat("%.2f");

QDateTimeAxis *axisX = new QDateTimeAxis(); // Using QValueAxis here instead makes the problem disappear.
axisX->setTitleText("Timestamp");
axisX->setTickCount(5);

chart->addAxis(axisX, Qt::AlignBottom);
chart->addAxis(axisY, Qt::AlignLeft);
series->attachAxis(axisX);
series->attachAxis(axisY);  

QChartView *chartView = new QChartView(chart);  
chartView->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing);

// Add some sample points.
QDateTime xval;
xval.setDate(QDate(2018, 1, 5));
series->append(xval.toMSecsSinceEpoch(), 3);
xval.setDate(QDate(2018, 1, 6));
series->append(xval.toMSecsSinceEpoch(), 6);
xval.setDate(QDate(2018, 1, 7));
series->append(xval.toMSecsSinceEpoch(), 4);

// Set ranges to display.
chart->axisX()->setRange(series->at(0).x(), series->at(series->count()-1).x()); 
chart->axisY()->setRange(0.0, 10.0);

This results in an empty chart with default X axis values ('01-01-1970 1:00' for all ticks), yet the same code renders the series correctly if QValueAxis is used instead of QDateTimeAxis.

What I tried:

  • chartView->repaint() - has no effect;
  • chart->removeSeries()/addSeries() to re-add the series after appending the data; this causes the series to be displayed, but X axis tick values are wrong: they all show default '01-01-1970 ...' labels, not the ones corresponding to the data. Even if this were a working solution, it shouldn't be necessary to remove and re-add the series.

I'm using Qt 5.9.2.

Why does QDateTimeAxis behave differently? Is there a way to make this work consistently regardless of axis type?


Solution

  • The solution is to use fromMSecsSinceEpoch() when setting axis range for data added with toMSecsSinceEpoch():

    axisX->setRange(
      QDateTime::fromMSecsSinceEpoch(series->at(0).x()), 
      QDateTime::fromMSecsSinceEpoch(series->at(series->count()-1).x())); 
    

    The series will then be displayed normally.