QCustomPlot Discussion and Comments

datetime labels styleReturn to overview

Here is a sample code:

    QVector<double> dates, weights;

    for (int i = 0; i < 15; ++i)
    {
        dates.push_back(QDateTime::currentDateTime().addDays(i).toTime_t());
        weights.push_back(qrand() % 10 + 70);
    }

    customPlot->addGraph();
    customPlot->graph(0)->setData(dates, weights);
    customPlot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 5));

    customPlot->xAxis->setTickLabelType(QCPAxis::ltDateTime);
    customPlot->xAxis->setDateTimeFormat("MMM dd");
    customPlot->xAxis->setLabel("Date");
    customPlot->yAxis->setLabel("Weight");

    customPlot->xAxis->setRange(dates.front(), dates.back());
    customPlot->yAxis->setRange(70, 80);

If you run it, you will see that on the resulting plot the points lie in between dates and also the distance between labels is not constant - sometimes it can be 2 days, sometimes it is 3 days. Is this a bug or am I missing something?

Here is a screenshot of the plot I obtain
https://dl.dropboxusercontent.com/u/1745619/dates.png

The reason why the points appear slightly after the exact lines is twofold: In the background, the tick labels are created depending on the double representation of the date (i.e. POSIX standard, seconds since 1.1.1970 0:00). So when you omit the time in your dateTimeFormat, you only get shown the month and day, but the time might be non-zero, so the label won't be at 12:00 (middle of the respective day). When using QDateTime::currentDateTime your points further include the current time, so they won't be at 12:00 (or 0:00) either. That might be intentional or not, depending on your application, but this is the reason why the points are not on the lines of your ticks.

You can take more control of the label positions, by either setting a fixed tick step or using a custom tick label position generator in reaction to the ticksRequest signal of the respective axis. An alternative is to subclass QCPAxis and reimplement generateAutoTicks. You can inject the subclasses via QCPAxisRect::addAxis(yourAxis)).

The second thing I'd like to point out is that you need to keep your timezone in mind, so have a look at QDateTime::setTimeSpec and QCPAxis::setDateTimeSpec. If the QDateTime you use to generate the numbers has a different timezone than the axis, you'll get according offsets.

Thank you for the explanation, it makes perfect sense. When I made the labels show time I saw that the time of day was all over the place from label to label, which explains why I saw interval inconsistencies between adjacent labels when I only displayed a date. Still, it is not clear to me that this is a sane behavior for a tick generation algorithm. And thank you for pointing to a way to reimplement it.

> Still, it is not clear to me that this is a sane behavior for a tick generation algorithm.

It's totally not. That's why it will change in QCP 2.0 ;)

Is 2.0 the next release version or a long-term plan?

Another question regarding axes, how can I obtain the pixel length of an axis?

There might be a 1.4 if it turns out enough features of 2.0 can be "back-ported" easily, but I plan to move QCP forward to 2.0 at this stage.

The pixel length of an axis can be obtained by looking at the width (for x axis) or height (y axis) of the respective axis rect. See QCPAxisRect::width()/height() or ::rect()

Alternatively you could do something like:
axis->coordToPixel(axis->range().upper) - axis->coordToPixel(axis->range().lower)
watch out for the sign change for vertical axes, might want to take the qAbs() of that.

how to label each data points with values????
Please help....