Как создать Subplot, используя QCharts? - PullRequest
1 голос
/ 04 марта 2020

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

#include <QApplication>
#include <QMainWindow>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QTime>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QDateTimeAxis>
#include <QValueAxis>
#include <QDebug>

QT_CHARTS_USE_NAMESPACE

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);

  // Open File
  QFile file("D:\\Projects\\Embedded\\ArduinoTempLogger\\01-21-18.txt");

  if( !file.open(QIODevice::ReadOnly|QIODevice::Text) )
  {
    qDebug() << "File don't exist";
    return  1;
  }
  QTextStream stream(&file);
  QLineSeries *adc_series = new QLineSeries();
  QLineSeries *temp_series = new QLineSeries();
  QDateTime datetime = QDateTime::currentDateTime();
  while( !stream.atEnd() )
  {
    QString line = stream.readLine();
    QStringList values = line.split(",");
    QTime time;
    time = QTime::fromString(values[0], "hh:mm:ss");
    datetime.setTime(time);
    adc_series->append( datetime.toMSecsSinceEpoch(), values[1].toUInt() );
    temp_series->append( datetime.toMSecsSinceEpoch(), values[2].toDouble() );
    // qDebug() << time.toString("hh:mm:ss") << "-->" << datetime.toMSecsSinceEpoch();
  }
  file.close();

  QChart *chart = new QChart();
  chart->legend()->hide();
  chart->addSeries(adc_series);
  chart->addSeries(temp_series);
  // chart->createDefaultAxes();
  chart->setTitle("Temperature Plot");

  // Since we use QLineSeries, calling createDefaultAxes will create QValueAxis both as X and Y axis.
  // To use QDateTimeAxis we need to set it manually to the chart.
  // First, the instance of QDateTimeAxis is created, then the number of ticks to be shown is set.
  //
  QDateTimeAxis *axisX = new QDateTimeAxis;
  axisX->setTickCount(10);
  axisX->setFormat("hh:mm:ss");
  axisX->setTitleText("Time Axis");
  chart->addAxis(axisX, Qt::AlignBottom);
  adc_series->attachAxis(axisX);
  temp_series->attachAxis(axisX);

  QValueAxis *axisY = new QValueAxis;
  axisY->setLabelFormat("%i");
  axisY->setTitleText("Temperature and ADC Value");
  axisY->setRange(0, 100);
  chart->addAxis(axisY, Qt::AlignLeft);
  adc_series->attachAxis(axisY);
  temp_series->attachAxis(axisY);

  QChartView *chartView = new QChartView(chart);
  chartView->setRenderHint(QPainter::Antialiasing);

  QMainWindow window;
  window.setCentralWidget(chartView);
  window.resize(820, 600);
  window.show();

  return a.exec();
}

Данные, которые я читаю из файла, имеют следующий формат.

16:08:45,50,24.4
16:08:46,47,22.9
16:08:47,60,29.3
16:08:48,45,22
16:08:49,49,23.9
16:08:50,54,26.4
16:08:51,46,22.5
16:08:52,40,19.5
16:08:53,50,24.4
16:08:54,50,24.4
16:08:55,50,24.4
16:08:56,59,28.8
16:08:57,49,23.9
16:08:58,62,30.3
16:08:59,58,28.3
16:09:00,47,22.9
16:09:01,54,26.4
16:09:02,61,29.8
16:09:03,47,22.9
16:09:04,50,24.4
16:09:05,55,26.9
16:09:06,46,22.5
16:09:07,60,29.3
16:09:08,49,23.9
16:09:09,57,27.8
16:09:10,42,20.5
16:09:11,49,23.9
16:09:12,56,27.3
16:09:13,64,31.3
16:09:14,51,24.9
16:09:15,53,25.9
16:09:16,57,27.8

Я использую Qt 5.14.1 на Windows 10 Может кто-нибудь, пожалуйста, помогите мне достичь этого? Заранее спасибо.

1 Ответ

1 голос
/ 05 марта 2020

Qt не предоставляет прямого решения, поэтому есть несколько альтернатив:

  • Создайте 2 QChartView и поместите их в QVBoxLayout.
  • Создайте 2 QChart и поместите их внутри QChartView с использованием QGraphicsLinearLayout.

Первый метод тривиален, поэтому я не буду показывать пример, однако, если я покажу код второго метода:

#include <QtWidgets>
#include <QtCharts>
QT_CHARTS_USE_NAMESPACE

class GraphicsView: public QGraphicsView{
public:
    GraphicsView(QWidget *parent=nullptr):QGraphicsView(parent){
        setScene(new QGraphicsScene);
        layout = new QGraphicsLinearLayout(Qt::Vertical);
        form = new QGraphicsWidget;
        form->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
        form->setLayout(layout);
        scene()->addItem(form);
        layout->setSpacing(0);
    }
    void addChart(QChart *chart){
        if(chart){
            layout->addItem(chart);
        }
    }
protected:
    void resizeEvent(QResizeEvent *event){
        if(scene())
            scene()->setSceneRect(QRect(QPoint(0, 0), event->size()));
        if(form)
            form->resize(event->size());
        QGraphicsView::resizeEvent(event);
    }
private:
    QGraphicsWidget *form;
    QGraphicsLinearLayout *layout;
};

static bool create_series(QLineSeries *adc_series, QLineSeries *temp_series){
    QFile file("D:\\Projects\\Embedded\\ArduinoTempLogger\\01-21-18.txt");

    if( !file.open(QIODevice::ReadOnly|QIODevice::Text)){
        qDebug() << "File don't exist";
        return false;
    }
    QTextStream stream(&file);
    QDateTime datetime = QDateTime::currentDateTime();
    while( !stream.atEnd()){
        QString line = stream.readLine();
        QStringList values = line.split(",");
        datetime.setTime(QTime::fromString(values[0], "hh:mm:ss"));
        adc_series->append( datetime.toMSecsSinceEpoch(), values[1].toUInt() );
        temp_series->append( datetime.toMSecsSinceEpoch(), values[2].toDouble() );
    }
    file.close();
    return true;
}


static QChart* create_chart(const QString & title, QLineSeries *series){
    QChart * chart = new QChart;
    chart->legend()->hide();
    chart->addSeries(series);

    QDateTimeAxis *axisX = new QDateTimeAxis;
    axisX->setTickCount(10);
    axisX->setFormat("hh:mm:ss");
    axisX->setTitleText("Time Axis");
    chart->addAxis(axisX, Qt::AlignBottom);
    series->attachAxis(axisX);

    QValueAxis *adc_axisY = new QValueAxis;
    adc_axisY->setLabelFormat("%i");
    adc_axisY->setTitleText(title);
    adc_axisY->setRange(0, 100);
    chart->addAxis(adc_axisY, Qt::AlignLeft);
    series->attachAxis(adc_axisY);
    return chart;
}

int main(int argc, char *argv[]){
    QApplication a(argc, argv);

    QLineSeries *adc_series = new QLineSeries;
    QLineSeries *temp_series = new QLineSeries;
    if(!create_series(adc_series, temp_series))
        return -1;

    GraphicsView view;
    view.addChart(create_chart("ADC Value", adc_series));
    view.addChart(create_chart("Temperature Value", temp_series));
    view.show();
    view.resize(640, 480);

    return a.exec();
}

enter image description here

С другой стороны, Qt не очень любит Qt Charts, поэтому простых задач, таких как вспомогательные сюжеты, не существует, поэтому я рекомендую использовать другие библиотеки, такие как QCustomPlot , которые предлагают такую ​​функциональность, в этой ссылке есть пример.

...