Search code examples
c++qt5axis-labelstimeserieschartqtcharts

How to plot non-consecutive time-series axis with QtCharts?


I need to plot a chart, whose axis X has data type of date-time.

I'm trying to use QtCharts to do so, but I find that QtCharts::QDateTimeAxis can only process consecutive data(the X axis is proportional and consecutive).

For example, given a LineSeries:

{
   { "20:15:00", 123.0 },
   { "20:15:01", 124.0 },
   { "21:00:00", 125.0 },
   { "21:00:01", 126.0 },
}

If I use a QDateTimeAxis as the X-axis, I would get too more white-space range on X axis, not only 4 spots.

Even though there is no data between "20:15:02" to "20:59::59", QChart still gives the space of a lot of slots in X axis that have no meaning.

Can we plot a chart that has non-consecutive X-axis with Qt?

If Qt cannot do it, is there a open-source C++ library that can do the same?


Solution

  • You don't have to use QDateTimeAxis since that axis is designed so that the points are spaced proportionally to the time difference. So one possible solution is to use QCategoryAxis:

    #include <QtWidgets>
    #include <QtCharts>
    
    QT_CHARTS_USE_NAMESPACE
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        std::vector<std::pair<QString, float>> data = {
            { "20:15:00", 123.0 },
            { "20:15:01", 124.0 },
            { "21:00:00", 125.0 },
            { "21:00:01", 126.0 },
        };
    
        QScatterSeries *series = new QScatterSeries(); // or QLineSeries *series = new QLineSeries;
        QCategoryAxis *axisX = new QCategoryAxis;
        axisX->setMin(.5);
        axisX->setMax(data.size() + .5);
        axisX->setTitleText("Time");
        QValueAxis *axisY = new QValueAxis;
        axisY->setLabelFormat("%.2f");
        axisY->setTitleText("Example");
        axisY->setMin(122);
        axisY->setMax(127);
    
        for(std::size_t i=0; i < data.size(); i++){
            series->append(i + 1, data.at(i).second);
            axisX->append(data.at(i).first, i + 1.5);
        }
    
        QChart *chart = new QChart();
        chart->addSeries(series);
    
        chart->legend()->hide();
        chart->addAxis(axisX, Qt::AlignBottom);
    
        series->attachAxis(axisX);
        chart->addAxis(axisY, Qt::AlignLeft);
        series->attachAxis(axisY);
    
        QChartView *chartView = new QChartView(chart);
        chartView->setRenderHint(QPainter::Antialiasing);
        QMainWindow window;
        window.setCentralWidget(chartView);
        window.resize(820, 600);
        window.show();
        return a.exec();
    }
    

    enter image description here