QTCharts, как мне сделать так, чтобы диаграмма следовала по оси x при поступлении данных в реальном времени?

Я пытаюсь создать диаграмму, которая читает данные в реальном времени. Я начал с примера, который Qt предоставляет под названием «динамический сплайн».

Проблема, с которой я столкнулся, заключается в том, что функция scroll (), кажется, прокручивает пиксели, и в Qt нет какой-либо функции, которую я могу найти, которая прокручивается вместе с данными. Поэтому, пока я не получу точное количество прокрутки пикселей, моя сюжетная линия будет расти до тех пор, пока конец больше не будет виден, или диаграмма будет прокручиваться, оставив сюжетную линию позади.

Для меня это похоже на довольно очевидную функцию, которую каждый использовал бы с динамической диаграммой, поэтому я остаюсь задавать вопрос: какая функция в диаграммах Qt мне не хватает, чтобы это сделать?

Все мои поиски были напрасными, я даже не смог найти учебник о том, как использовать динамический сбор данных в диаграммах Qt.

#include "chart.h"
#include <QtCharts/QAbstractAxis>
#include <QtCharts/QSplineSeries>
#include <QtCharts/QValueAxis>
#include <QtCore/QTime>
#include <QtCore/QDebug>

Chart::Chart(QGraphicsItem *parent, Qt::WindowFlags wFlags):
    QChart(QChart::ChartTypeCartesian, parent, wFlags),
    m_series(0),
    m_axis(new QValueAxis),
    m_step(0),
    m_x(10),
    m_y(1)
{
    qsrand((uint) QTime::currentTime().msec());

    QObject::connect(&m_timer, SIGNAL(timeout()), this, SLOT(drawChart()));
    m_timer.setInterval(1000);

    m_series = new QSplineSeries(this);
    QPen green(Qt::red);
    green.setWidth(3);
    m_series->setPen(green);
    m_series->append(m_x, m_y);

    addSeries(m_series);
    createDefaultAxes();
    setAxisX(m_axis, m_series);
//    m_axis->setTickCount(11);
    axisX()->setRange(0, 100);
    axisY()->setRange(-5, 10);

    m_timer.start();
    elapsedTime.start();
}

Chart::~Chart()
{

}

void Chart::drawLine(qreal &x, qreal &y)
{
    m_series->append(x, y);
}

qreal Chart::getTime()
{
    return elapsedTime.elapsed() / 100;
}

void Chart::drawChart()
{
    qreal x = plotArea().width() / m_axis->tickCount();
    qreal y = (m_axis->max() - m_axis->min()) / m_axis->tickCount();
    m_x = getTime();
    m_y = qrand() % 5 - 2.5;
    drawLine(m_x, m_y);
    scroll(x, 0);

    qDebug() << getTime();
}

Код довольно прост, прямо сейчас он рисует, но линия и прокрутка полностью вышли из строя. И поскольку я хочу использовать время в качестве оси X и не могу использовать приятный немасштабируемый способ настройки примера.

Прямо сейчас он просто рисует случайное число. Я не собираюсь кормить его фактическими данными, пока не разберусь с этой прокруткой.

Заранее спасибо за помощь. И если вы знаете несколько хороших руководств по диаграммам Qt, я был бы очень признателен. Руководства по Qt, в любом случае хорошие, найти чрезвычайно сложно.


person granitdev    schedule 09.02.2017    source источник


Ответы (2)


После долгих усилий и бросания вещей об стену, чтобы посмотреть, что застряло, я обнаружил, что свиток - не то, что вам следует использовать. Вы хотите связать диапазон с вашим значением x и обновлять его каждый раз, когда вы добавляете данные. Это заставляет график как бы прокручиваться вместе со строкой данных.

Новая проблема, диаграммы в Qt имеют встроенную утечку памяти.

person granitdev    schedule 12.02.2017
comment
Хотите поделиться своими выводами? - person Django; 21.08.2018
comment
Больше нечего добавить. Я перестал пользоваться Qt Charts. Отнюдь не болезненный, громоздкий и медленный, а также утечка памяти как siv, я переключился на pyqtgraph и выполнил то, что намеревался сделать на python. Как обычно, если ничего не работает, просто сделайте это на Python. - person granitdev; 23.08.2018
comment
Спасибо за ответ. Я видел несколько сообщений об утечках памяти через QCharts, но, похоже, они решены. Когда у вас появляется эта проблема? - person Django; 23.08.2018

Вместо прокрутки попробуйте изменить максимальное значение осиX.

Когда вы выполняете DrawLine, проверьте, не превышает ли следующая точка максимальное значение, и установите новый максимум, если да:

if (m_x > m_axisX->max())
{
        m_axisX->setMax(m_x);
}
person Dinendal    schedule 24.02.2017
comment
Максимум не обязательно отображается. Без изменения диапазона макс потечет сразу с экрана без нареканий. - person granitdev; 31.03.2017