Реклама

Qt/C++ - Урок 031. QCustomPlot - строим график по времени

TutorialQtQCustomPlot, QDateTime, Qt, время, график383

Библиотека QCustomPlot имеет возможность построения графиков по шкале времени, что удобно при анализе данных, которые изменяются во времени. Для этого необходимо установить тип подписи к Оси Времени в качестве QCPAxis::ltDateTime. И после этого выставить формат даты и времени. То есть имеется возможность отображать на Оси или дату, или время, или одновременно и то и другое, в зависимости от того, какое форматирование Вы зададите. Правила форматирования для QCustomPlot используются те же, что и для классов QDateTime, QDate, QTime.

Координата времени передаётся в виде числа типа double , которое начинает отсчёт в секундах от времени 1970-01-01T00:00:00 . Что необходимо учитывать при построении графика.

Предлагаю написать приложение, которое будет строить псевдослучайный график дохода и рублях в зависимости от текущей координаты времени. При этом с графиком можно будет взаимодействовать, то есть приближать и удалять его, а также передвигать, но только по горизонтальной Оси. То есть по высоте отображение графика изменяться не будет. Также сделаем возможность изменения формат координат времени в зависимости видимой области графика по Оси Времени. То есть, если видна часть графика меньше, чем за один день, то по оси времени формат подписей будет следующий: hh:mm . В противном случае формат будет "dd MMM yy" .

Строим График

Создаём проект и подключаем в него библиотеку QCustomPlot. Модификации будут подвергаться только файлы mainwindow.h и mainwindow.cpp. Новые файлы добавляться не будут.

mainwindow.h

Объявляем экземпляр класса QCustomPlot, а также экземпляр самого графика. И объявим СЛОТ, в который будет передаваться сигнал об изменении области отображения по Оси Времени.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "qcustomplot.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    QCustomPlot *customPlot;    // Объявляем графическое полотно
    QCPGraph *graphic;          // Объявляем график

private slots:
    void slotRangeChanged (const QCPRange &newRange);
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    customPlot = new QCustomPlot(); // Инициализируем графическое полотно
    ui->gridLayout->addWidget(customPlot,0,0,1,1);  // Устанавливаем customPlot в окно проложения

    customPlot->setInteraction(QCP::iRangeZoom,true);   // Включаем взаимодействие удаления/приближения
    customPlot->setInteraction(QCP::iRangeDrag, true);  // Включаем взаимодействие перетаскивания графика
    customPlot->axisRect()->setRangeDrag(Qt::Horizontal);   // Включаем перетаскивание только по горизонтальной оси
    customPlot->axisRect()->setRangeZoom(Qt::Horizontal);   // Включаем удаление/приближение только по горизонтальной оси
    customPlot->xAxis->setTickLabelType(QCPAxis::ltDateTime);   // Подпись координат по Оси X в качестве Даты и Времени
    customPlot->xAxis->setDateTimeFormat("hh:mm");  // Устанавливаем формат даты и времени

    // Настраиваем шрифт по осям координат
    customPlot->xAxis->setTickLabelFont(QFont(QFont().family(), 8));
    customPlot->yAxis->setTickLabelFont(QFont(QFont().family(), 8));

    // Автоматическое масштабирование тиков по Оси X
    customPlot->xAxis->setAutoTickStep(true);

    /* Делаем видимыми оси X и Y по верхней и правой границам графика,
     * но отключаем на них тики и подписи координат
     * */
    customPlot->xAxis2->setVisible(true);
    customPlot->yAxis2->setVisible(true);
    customPlot->xAxis2->setTicks(false);
    customPlot->yAxis2->setTicks(false);
    customPlot->xAxis2->setTickLabels(false);
    customPlot->yAxis2->setTickLabels(false);

    customPlot->yAxis->setTickLabelColor(QColor(Qt::red)); // Красный цвет подписей тиков по Оси Y
    customPlot->legend->setVisible(true);   //Включаем Легенду графика
    // Устанавливаем Легенду в левый верхний угол графика
    customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignLeft|Qt::AlignTop);

    // Инициализируем график и привязываем его к Осям
    graphic = new QCPGraph(customPlot->xAxis, customPlot->yAxis);
    customPlot->addPlottable(graphic);  // Устанавливаем график на полотно
    graphic->setName("Доход, Р");       // Устанавливаем
    graphic->setPen(QPen(QColor(Qt::red))); // Устанавливаем цвет графика
    graphic->setAntialiased(false);         // Отключаем сглаживание, по умолчанию включено
    graphic->setLineStyle(QCPGraph::lsImpulse); // График в виде импульсных тиков

    /* Подключаем сигнал от Оси X об изменении видимого диапазона координат
     * к СЛОТу для переустановки формата времени оси.
     * */
    connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)),
            this, SLOT(slotRangeChanged(QCPRange)));

    // Будем строить график с сегодняшнего дни и текущей секунды в будущее
    double now = QDateTime::currentDateTime().toTime_t();
    // Объявляем вектора времени и доходов
    QVector <double> time(400), income(400);

    srand(15); // Инициализируем генератор псевдослучайных чисел

    // Заполняем график значениями
    for (int i=0; i<400; ++i)
      {
        time[i] = now + 3600*i;
        income[i] = qFabs(income[i-1]) + (i/50.0+1)*(rand()/(double)RAND_MAX-0.5);
      }

    graphic->setData(time, income); // Устанавливаем данные
    customPlot->rescaleAxes();      // Масштабируем график по данным
    customPlot->replot();           // Отрисовываем график
}

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

void MainWindow::slotRangeChanged(const QCPRange &newRange)
{
    /* Если область видимости графика меньше одного дня,
     * то отображаем часы и минуты по Оси X,
     * в противном случае отображаем дату "День Месяц Год"
     * */
    customPlot->xAxis->setDateTimeFormat((newRange.size() <= 86400)? "hh:mm" : "dd MMM yy");
}

Итог

В результате у Вас должен получиться график подобный тому, что показан на ниже следующем рисунке. Отмечу, что при прокручивании колёсика мыши и передвижении графика мышью, сам График будет изменяться только по Оси X, как и было задумано в данном примере.

Демонстрацию работы приложения Вы можете увидеть в видеоуроке.

Видеоурок

@EVILEG 27 декабря 2015 г. 20:09

Реклама

Реклама

Комментарии

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь

Реклама

Реклама