Russian Qt Forum

Qt => Вопросы новичков => Тема начата: sektor от Март 14, 2017, 17:13



Название: QChart
Отправлено: sektor от Март 14, 2017, 17:13
Хочу реализовать простую программу (график ось х время, ось У числа). Есть виджет с кнопкой и ввод числа. Хочу при нажатии на кнопку, чтобы число в dublespinbox добавилась на ось У а на ось Ч время.
 
Код:
#include "chart.h"
#include "ui_chart.h"

chart::chart(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::chart)
{
    ui->setupUi(this);

    //qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));

    series = new QLineSeries();
    series->append(momentInTime.toMSecsSinceEpoch(),0);
    m_chart = new QChart();
    m_chart->addSeries(series);
    m_chart->legend()->hide();
    m_chart->setTitle("Sunspots count (by Space Weather Prediction Center)");
    //![3]

    //![4]
    axisX = new QDateTimeAxis;
    axisX->setTickCount(10);
    //axisX->setFormat("MMM yyyy");
    axisX->setTitleText("Date");
    m_chart->addAxis(axisX, Qt::AlignBottom);
    series->attachAxis(axisX);

    axisY = new QValueAxis;
    axisY->setLabelFormat("%i");
    axisY->setTitleText("Sunspots count");
    m_chart->addAxis(axisY, Qt::AlignLeft);
    series->attachAxis(axisY);
    //![4]

    //![5]
    chartView = new QChartView(m_chart);
    chartView->setRenderHint(QPainter::Antialiasing);
    ui->gridLayout->addWidget(chartView);

}

chart::~chart()
{
    delete ui;
}

void chart::on_pushButton_clicked()
{
    m_chart->removeSeries(series);
    series->append(momentInTime.toMSecsSinceEpoch(), ui->doubleSpinBox->value());
    m_chart->addSeries(series);
}


Название: Re: QChart
Отправлено: Пантер от Март 14, 2017, 21:15
Ты спросить что-то хотел или так, поделиться?


Название: Re: QChart
Отправлено: sektor от Март 15, 2017, 07:46
Конечно спросить  ;) мой код не работает. Как это реализовать ? Если я использую не врямя по оси X  а точки то все получается с времененм ничего не получается


Название: Re: QChart
Отправлено: VPS от Март 15, 2017, 11:58
Можно попробовать расширять диапазон по осям, например так:
Код:
void MainWindow::on_pushButton_clicked()
{
   QDateTime minX = axisX->min();
   QDateTime maxX = axisX->max();

   qreal minY = axisY->min();
   qreal maxY = axisY->max();

   QDateTime x = QDateTime::currentDateTime();
   qreal y = ui->doubleSpinBox->value();

   axisX->setRange(minX, x > maxX ? x : maxX);
   axisY->setRange(minY, y > maxY ? y : maxY);
   series->append(x.toMSecsSinceEpoch(), y);
}

Если же диапазон максимальных и минимальных значений по осям не будет изменяться, то можно использовать сигнально-слотовое соединение в конструкторе:
Код:
connect(series, SIGNAL(pointAdded(int)), chartView, SLOT(update()));


Название: Re: QChart
Отправлено: sektor от Март 15, 2017, 16:49
спасибо получилось без сигналов. Я думал он автоматом масштабирует. Дрогой вопрос допустим я хочу только 10 точек отобразить на графике, то есть при добавлении 11 первая удаляется и все сдвигаются тем самым на графике только 10 последних значений. Чтобы это реализовать нужно все вручную делать? перезаписывать QPoin  или же можно функцией scroll воспользоваться. Будет ли утечка памяти ?


Название: Re: QChart
Отправлено: ViTech от Март 15, 2017, 17:17
Будет ли утечка памяти?

Я пробовал двигать с помощью axisX->setRange(), правда не знаю, насколько это правильно. И после нескольких таких "движений" вывод графика начинает дико тормозить. А QChart, похоже, и без посторонней помощи течёт: QCharts Memory Leak (https://bugreports.qt.io/browse/QTBUG-58802) :).


Название: Re: QChart
Отправлено: sektor от Март 16, 2017, 13:42
Движение как показано в примере нужно осуществлять функцией scroll (QChart ) как я понял.   


Название: Re: QChart
Отправлено: ViTech от Март 16, 2017, 14:24
Да, с помощью QChart::scroll() тоже двигается график. Но отжирание памяти и тормоза так же накапливаются как и при axisX->setRange(). Даже при пустой координатной сетке, без отображения данных.


Название: Re: QChart
Отправлено: sektor от Март 16, 2017, 17:18
Ты не решил проблему с утечкой памяти? Наверное оно возникает при добавление в QLineSerias записей. МОжет попробовать replace Qpoint делать ?


Название: Re: QChart
Отправлено: ViTech от Март 16, 2017, 21:12
В пользовательском коде нечему течь. Или я чего-то не знаю :).

Код
C++ (Qt)
#include <QApplication>
#include <QMainWindow>
#include <QChartView>
#include <QChart>
#include <QLineSeries>
#include <QValueAxis>
#include <QDateTimeAxis>
#include <QDateTime>
#include <QGraphicsSceneMouseEvent>
 
using namespace QtCharts;
 
const int SecsInHour = 3600;
 
class MyChart : public QChart
{
protected:
   void mousePressEvent(QGraphicsSceneMouseEvent *event) override
   { event->accept(); }
   void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override
   {
       if (event->buttons().testFlag( Qt::LeftButton) )
       {
           #if 1
           scroll(event->lastPos().x() - event->pos().x(), 0);
           #else
           qint64 secs = SecsInHour / 2;
           if (event->pos().x() > event->lastPos().x())
               secs = -secs;
           QDateTimeAxis * axis_x = qobject_cast<QDateTimeAxis *>(axisX());
           QDateTime current = axis_x->min();
           current = current.addSecs( secs );
           axis_x->setRange(current, current.addDays(1));
           #endif
       }
   }
};
 
int main(int argc, char *argv[])
{
   QApplication application(argc, argv);
 
   QDateTime current(QDate::currentDate(), QTime());
 
   QLineSeries *series = new QLineSeries;
   series->append(current.addSecs(SecsInHour * 1 ).toMSecsSinceEpoch() , 25);
   series->append(current.addSecs(SecsInHour * 2 ).toMSecsSinceEpoch() , 75);
   series->append(current.addSecs(SecsInHour * 3 ).toMSecsSinceEpoch() , 25);
 
   QDateTimeAxis *axisX = new QDateTimeAxis();
   axisX->setRange(current, current.addDays(1));
   axisX->setTickCount(12);
   axisX->setFormat("dd.MM hh:00");
 
   QValueAxis *axisY = new QValueAxis();
   axisY->setRange(0, 100);
 
   MyChart *chart = new MyChart();
   chart->legend()->hide();
   chart->addSeries(series);
   chart->setAxisX(axisX, series);
   chart->setAxisY(axisY, series);
 
   QChartView *chart_view = new QChartView(chart);
 
   QMainWindow main_window;
   main_window.setCentralWidget(chart_view);
   main_window.resize(1000, 600);
   main_window.show();
 
   return application.exec();
}
 

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


Название: Re: QChart
Отправлено: sektor от Март 16, 2017, 21:32
я собираю 100 точек на графике с интервалом 5 сек. После того как добавятся все 100 точек на график я начинаю сдвигать график, то есть всегда на графике последнее 100 точек. Так вот, я в диспетчере задач смотрю память она растет и растет не знаю что делать  ???.


Название: Re: QChart
Отправлено: VPS от Март 16, 2017, 21:40
я собираю 100 точек на графике с интервалом 5 сек. После того как добавятся все 100 точек на график я начинаю сдвигать график, то есть всегда на графике последнее 100 точек. Так вот, я в диспетчере задач смотрю память она растет и растет не знаю что делать  ???.
Вы при этом удаляете точки, которые не отображаются на графике из QLineSeries?


Название: Re: QChart
Отправлено: sektor от Март 16, 2017, 21:51
Цитировать
Вы при этом удаляете точки, которые не отображаются на графике из QLineSeries?
нет не удаляю. Про скройлинге они не удаляются ?


Название: Re: QChart
Отправлено: VPS от Март 16, 2017, 22:07
Цитировать
Вы при этом удаляете точки, которые не отображаются на графике из QLineSeries?
нет не удаляю. Про скройлинге они не удаляются ?
Думаю, что нет. Да и в описании к методу про это ничего не сказано.


Название: Re: QChart
Отправлено: sektor от Март 16, 2017, 22:46
посмотрите пример Dynamic Spline Example, там вроде ничего не удаляется 


Название: Re: QChart
Отправлено: VPS от Март 16, 2017, 23:47
Можете проверить выводом количества точек в серии: int QXYSeries::count() const (http://doc.qt.io/qt-5/qxyseries.html#count)


Название: Re: QChart
Отправлено: sektor от Март 17, 2017, 13:49
maxPoint =50 точек. Я даже сделал так, чтобы после 50 точек программа перезаписывала точки. int QXYSeries::count() const показывает 50 но память все жрет и через 5 мин программу жутко тормозит.
Код:
bool ChartMonitoring::setData(QString name, float data)
{
    QDateTime minX = axisXX->min();
    QDateTime maxX = axisXX->max();

    qreal minY = axisYY.value(name)->min();
    qreal maxY = axisYY.value(name)->max();

    QDateTime x = QDateTime::currentDateTime();
    qreal y = data;
    QPointF pointer;

     if(point.value(name)==maxPoint) {
        reng = maxX.toMSecsSinceEpoch()-minX.toMSecsSinceEpoch();
        //qDebug() <<reng;
     }

     if(point.value(name)>=maxPoint) {
         timeRenge.setMSecsSinceEpoch(x.toMSecsSinceEpoch()-reng);

         axisXX->setRange(timeRenge, x>maxX ? x : maxX);
         for(int i=0; i<maxPoint-1; i++){
            pointer = serias.value(name)->at(i+1);
            serias.value(name)->replace(i, pointer);
         }
         pointer.setX(x.toMSecsSinceEpoch());
         pointer.setY(y);
         serias.value(name)->replace(maxPoint-1, pointer);
     }
    else {
         axisXX->setRange(minX, x>maxX ? x : maxX);
         serias.value(name)->append(x.toMSecsSinceEpoch(), y);
         point[name]++;

     }

     qDebug() << serias.value(name)->count();
}




Название: Re: QChart
Отправлено: ViTech от Март 17, 2017, 14:52
При каждом QXYSeries::replace(int index, const QPointF &newPoint) испускается сигнал QXYSeries::pointReplaced(int index), т.е. при каждом перезаписывании всех точек таких сигналов получается порядка 50, что производительности не добавляет. Лучше делать QXYSeries::remove() первой точки, и новую добавлять с помощью QXYSeries::append(). И соответственно оси двигать.

Но полагаю, что течёт и тормозит где-то во внутренностях QChart (https://bugreports.qt.io/browse/QTBUG-58802). Когда это исправят - не известно... Зато можно приделать "some ‘wow’-effect" и наслаждаться Glowing Qt Charts (http://blog.qt.io/blog/2017/02/07/glowing-qt-charts/) :).


Название: Re: QChart
Отправлено: sektor от Март 17, 2017, 15:49
Сделал как вы говорили удалять точки потом добавлять, никаких изменений   :'(


Название: Re: QChart
Отправлено: sektor от Март 17, 2017, 16:18
Да че тут говорить, посмотрите пример dinamicspline, память жрет  :) после 400 сек у меня тормоза начинаются


Название: Re: QChart
Отправлено: ViTech от Март 17, 2017, 16:19
В QCharts Memory Leak (https://bugreports.qt.io/browse/QTBUG-58802) пишут, что вроде помогает удалить из графика серию, создать новую и добавить её в график. Такой вот костыль. Хотя не удивлюсь, что тормозить будет если даже не добавлять в график никаких серий. У меня есть подозрения, что течёт и тормозит QChart просто с осями, в частности с QDateTimeAxis.