feedc0de
feedc0de

Reputation: 3796

How to automatically rescale axis in QtCharts?

I am using QtCharts.

I need both axes to be rescaled after appending values. The values I appended are not between 0 and 1 and also not from the year 1970.

QtChart axis wrong scaled

Constructor code of my dialog looks like this:

m_series = new QLineSeries;
m_series->setName(name);

auto chart = new QChart;
chart->legend()->setVisible(false);
chart->addSeries(m_series);

m_axisX = new QDateTimeAxis;
//m_axisX->setFormat("HH:mm:ss");
m_axisX->setTitleText(tr("Zeitpunkt"));
chart->addAxis(m_axisX, Qt::AlignBottom);

m_series->attachAxis(m_axisX);

auto axisY = new QValueAxis;
axisY->setTitleText(unit);
chart->addAxis(axisY, Qt::AlignLeft);

m_series->attachAxis(axisY);

auto chartView = new QChartView(chart, this);
chartView->setRenderHint(QPainter::Antialiasing);

My MainWindow emits signals containg new values. Multiple opened chart dialogs are connected to that signal.

void ChartDialog::liveUpdate(const RealTimeMeasureRegisters &registers)
{
    auto result = ((&registers)->*m_methodPtr)();

    m_series->append(registers.timestamp(), result);
}

Is there some easy way to tell QDateTimeAxis (in my case m_axisX) to automatically adjust to the new values?

QDateTimeAxis::setRange() does not look good, because I need to set a minimum and maximum.

Upvotes: 9

Views: 13577

Answers (3)

user2019716
user2019716

Reputation: 643

QLineSeries inherits from QXYSeries, which implements certain signals that you can exploit as follow :

connect(m_series, &QXYSeries::pointAdded,
        this, &MyForm::autoScaleChart);

in your form or model, better define chart and series as members, so that you can acces them from a member method called autoScaleChart (no need for a slot in Qt5)

#include <QMainWindow>
#include <QtCharts/QtCharts>
#include <math>
...

class MyForm :: QMainWindow
{
  Q_OBJECT
  public:
  ....

  private:
  QLineSeries* _series;
  QValueAxis* _xaxis;
  QValueAxis* _yaxis;
  QChart* _chart;
  void MyForm::autoScaleChart()
  {
    const QVector<QPointF>& dataVector = _tempSeries.pointsVector();
    double xMin = std::numeric_limits<double>::max();
    double xMax = std::numeric_limits<double>::min();
    double yMin = xMin;
    double yMax = xMax;
    for (auto p : dataVector)
    {
       xMin = qMin(xMin, p.x());
       xMax = qMax(xMax, p.x());
       yMin = qMin(yMin, p.y());
       yMax = qMax(yMax, p.y());
    }

    double xMargin = (xMax-xMin)/10.0;
    _xaxis.setRange(xMin-xMargin,xMax+xMargin);

    double yMargin = (yMax-yMin)/10.0;
    _yaxis.setRange(yMin-yMargin,yMax+yMargin);
  }
}

You can adapt the algorithm for more comprehensive one or datetime axis.

Upvotes: 0

ytexas
ytexas

Reputation: 11

About the first parameter in m_series->append(). Use "qint64 QDateTime::toMSecsSincPoch()" is better.... like:

...
m_series->append(QDateTime::currentDateTime().toMSecsSincPoch(), result);

Upvotes: 0

Dinendal
Dinendal

Reputation: 279

I don't know about a way to adjust automatically but you could look at this example which add points to the chart dynamically : http://doc.qt.io/qt-5/qtcharts-dynamicspline-example.html

Although in this example the range has been limited when adding points so to go further it would require to re-adjust the range when the next point is out of it.

As you say the setRange requires a min and a max but you could update it in your liveUpdate.

Upvotes: 1

Related Questions