Newer
Older
ZXSSCJ / CounterRealTime / ChannelChartForm.cpp
#include "ChannelChartForm.h"
#include "ui_ChannelChartForm.h"

ChannelChartForm::ChannelChartForm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ChannelChartForm)
{
    ui->setupUi(this);
    setAttribute(Qt::WA_DeleteOnClose); // 窗口关闭后释放本对象

    this->setWindowFlags(Qt::FramelessWindowHint);
    resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);

    QFile file(":/qss/chartForm.css");
    if (file.open(QFile::ReadOnly)) {
        QString qss = QLatin1String(file.readAll());
        QString paletteColor = qss.mid(20, 7);
        this->setPalette(QPalette(QColor(paletteColor)));
        this->setStyleSheet(qss);

        file.close();
    }
}

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

void ChannelChartForm::setTitleText(QString titleText)
{
    ui->labChartTitle->setText(titleText);
}

void ChannelChartForm::initDataChart(QList<QStringList> hisDataVect)
{
    QPen pen;
    pen.setColor(QColor("#2ed573")); // 曲线颜色(绿色)
    pen.setWidth(1); //曲线线宽

    QCPGraph * graph = ui->dataPlot->addGraph();
    graph->setName("钟差(ns)");
    graph->setAdaptiveSampling(true);    // 默认启用自适应采样(绘图)
    graph->setPen(pen);

    QCPGraph * graphResi = ui->analysisPlot->addGraph();
    graphResi->setName("钟差(ns)");
    graphResi->setAdaptiveSampling(true);    // 默认启用自适应采样(绘图)
    graphResi->setPen(pen);

    // 时间坐标轴  seconds since Epoch (January 1, 1970, 00:00 UTC).
    QSharedPointer<QCPAxisTickerDateTime> timeTicker(new QCPAxisTickerDateTime);
    timeTicker->setDateTimeFormat("MM-dd hh:mm:ss");    // 横轴刻度单位:分钟
    ui->dataPlot->xAxis->setTicker(timeTicker);
    ui->dataPlot->yAxis->setNumberFormat("gbc");       // Y 轴:g灵活的格式,b漂亮的指数形式,c乘号改成×
    ui->dataPlot->yAxis->setNumberPrecision(12);       // Y 轴:精度,有效数字的位数

    ui->analysisPlot->xAxis->setTicker(timeTicker);
    ui->analysisPlot->yAxis->setNumberFormat("gbc");       // Y 轴:g灵活的格式,b漂亮的指数形式,c乘号改成×
    ui->analysisPlot->yAxis->setNumberPrecision(12);       // Y 轴:精度,有效数字的位数

    ui->dataPlot->setBackground(QColor("#0B1425"));
    ui->analysisPlot->setBackground(QColor("#0B1425")); // 背景色

    ui->dataPlot->xAxis->setBasePen(QPen(Qt::white));
    ui->dataPlot->xAxis->setTickPen(QPen(Qt::white));
    ui->dataPlot->xAxis->setPadding(5);
    ui->dataPlot->xAxis->grid()->setVisible(true);
    ui->dataPlot->xAxis->grid()->setPen(QPen(QColor(130, 130, 130), 0, Qt::DotLine));
    ui->dataPlot->xAxis->setTickLabelColor(Qt::white);
    ui->dataPlot->xAxis->setLabelColor(Qt::white);
    ui->dataPlot->xAxis->setLabel("时间");

    ui->analysisPlot->xAxis->setBasePen(QPen(Qt::white));
    ui->analysisPlot->xAxis->setTickPen(QPen(Qt::white));
    ui->analysisPlot->xAxis->setPadding(5);
    ui->analysisPlot->xAxis->grid()->setVisible(true);
    ui->analysisPlot->xAxis->grid()->setPen(QPen(QColor(130, 130, 130), 0, Qt::DotLine));
    ui->analysisPlot->xAxis->setTickLabelColor(Qt::white);
    ui->analysisPlot->xAxis->setLabelColor(Qt::white);
    ui->analysisPlot->xAxis->setLabel("时间");

    ui->dataPlot->yAxis->setPadding(5); // a bit more space to the left border
    ui->dataPlot->yAxis->setLabel("钟差(ns)");
    ui->dataPlot->yAxis->setBasePen(QPen(Qt::white));
    ui->dataPlot->yAxis->setTickPen(QPen(Qt::white));
    //ui->dataPlot->yAxis->setSubTickPen(QPen(Qt::white));
    //ui->dataPlot->yAxis->grid()->setSubGridVisible(true);
    ui->dataPlot->yAxis->setTickLabelColor(Qt::white);
    ui->dataPlot->yAxis->setLabelColor(Qt::white);
    ui->dataPlot->yAxis->grid()->setPen(QPen(QColor(130, 130, 130), 0, Qt::SolidLine));
    //ui->dataPlot->yAxis->grid()->setSubGridPen(QPen(QColor(130, 130, 130), 0, Qt::DotLine));

    ui->analysisPlot->yAxis->setPadding(5); // a bit more space to the left border
    ui->analysisPlot->yAxis->setLabel("钟差(ns)");
    ui->analysisPlot->yAxis->setBasePen(QPen(Qt::white));
    ui->analysisPlot->yAxis->setTickPen(QPen(Qt::white));
    //ui->analysisPlot->yAxis->setSubTickPen(QPen(Qt::white));
    //ui->analysisPlot->yAxis->grid()->setSubGridVisible(true);
    ui->analysisPlot->yAxis->setTickLabelColor(Qt::white);
    ui->analysisPlot->yAxis->setLabelColor(Qt::white);
    ui->analysisPlot->yAxis->grid()->setPen(QPen(QColor(130, 130, 130), 0, Qt::SolidLine));
    //ui->analysisPlot->yAxis->grid()->setSubGridPen(QPen(QColor(130, 130, 130), 0, Qt::DotLine));

    double minTm = hisDataVect.first().at(0).toLongLong() / 1000;
    double maxTm = hisDataVect.last().at(0).toLongLong() / 1000;
    double minValue = hisDataVect.first().at(1).toDouble() * 1E9;
    double maxValue = hisDataVect.last().at(1).toDouble() * 1E9;
    QVector<QCPGraphData> vecPoints;

    double minResidual = 0.0;
    double maxResidual = 0.0;
    QVector<QCPGraphData> resiPoints;

    QPen tpen;
    tpen.setColor(QColor("#F1C40F")); // 曲线颜色(yellow)
    tpen.setWidth(2); // 线宽
    tpen.setStyle(Qt::DashDotLine);

    tracer = new QCPItemTracer(ui->dataPlot); //生成游标
    tracer->setStyle(QCPItemTracer::tsCrosshair);
    tracer->setPen(tpen);

    tracerResi = new QCPItemTracer(ui->analysisPlot); //生成游标
    tracerResi->setStyle(QCPItemTracer::tsCrosshair);
    tracerResi->setPen(tpen);

    connect(ui->dataPlot, &QCustomPlot::mouseMove, this, &ChannelChartForm::mouseMoveEvent);
    connect(ui->analysisPlot, &QCustomPlot::mouseMove, this, &ChannelChartForm::showTracerResidual);

    double timeVec[hisDataVect.size()];
    double valueVec[hisDataVect.size()];

    for (int i = 0; i < hisDataVect.size(); i++)
    {
        // 新的数据点
        QCPGraphData onePoint;

        QDateTime dtime = QDateTime::fromSecsSinceEpoch(hisDataVect.at(i).at(0).toLongLong() / 1000);    // 日期时间
        onePoint.key = QCPAxisTickerDateTime::dateTimeToKey(dtime);
        onePoint.value = hisDataVect.at(i).at(1).toDouble() * 1E9;

        timeVec[i] = onePoint.key;
        valueVec[i] = onePoint.value;

        vecPoints.append(onePoint);

        if (hisDataVect.at(i).at(1).toDouble() * 1E9 < minValue)
        {
            minValue = hisDataVect[i].at(1).toDouble() * 1E9;
        }

        if (hisDataVect.at(i).at(1).toDouble() * 1E9 > maxValue)
        {
            maxValue = hisDataVect[i].at(1).toDouble() * 1E9;
        }
    }

    graph->data()->clear();
    graph->data()->set(vecPoints, true);
    ui->dataPlot->xAxis->setRange(minTm, maxTm);
    ui->dataPlot->yAxis->setRange(minValue, maxValue);

    ui->dataPlot->legend->setVisible(false);
    ui->dataPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); // 设置曲线可以拖动 可以缩放

    // 计算残差部分
    LinearRegression lineReg;
    lineReg.xArray = timeVec;
    lineReg.yArray = valueVec;
    lineReg.calcLineRegParams(hisDataVect.size());
    for (int i = 0; i < hisDataVect.size(); i++)
    {
        // 新的残差数据点
        QCPGraphData resiPoint;

        QDateTime dtime = QDateTime::fromSecsSinceEpoch(hisDataVect.at(i).at(0).toLongLong() / 1000);    // 日期时间
        resiPoint.key = QCPAxisTickerDateTime::dateTimeToKey(dtime);
        resiPoint.value = hisDataVect.at(i).at(1).toDouble() * 1E9 - (lineReg.slope * resiPoint.key + lineReg.intercept);

        resiPoints.append(resiPoint);
        if (resiPoint.value < minResidual)
        {
            minResidual = resiPoint.value;
        }

        if (resiPoint.value > maxResidual)
        {
            maxResidual  = resiPoint.value;
        }
    }

    graphResi->data()->clear();
    graphResi->data()->set(resiPoints, true);
    ui->analysisPlot->xAxis->setRange(minTm, maxTm);
    ui->analysisPlot->yAxis->setRange(minResidual, maxResidual);

    ui->analysisPlot->legend->setVisible(false);
    ui->analysisPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); // 设置曲线可以拖动 可以缩放
}

void ChannelChartForm::on_btnChartClose_clicked()
{
    this->close();
}

void ChannelChartForm::mouseMoveEvent(QMouseEvent *event)
{
    //将像素点转换成qcustomplot中的坐标值,并通过setGraphKey将锚点值设为真实数据值。tracer->setGraphKey(xAxis->pixelToCoord(event->pos().x()));

    //获得鼠标位置处对应的横坐标数据x
    qulonglong x = ui->dataPlot->xAxis->pixelToCoord(event->pos().x());
    this->drawPlotTracer(x);
}

void ChannelChartForm::showTracerResidual(QMouseEvent *event)
{
    //获得鼠标位置处对应的横坐标数据x
    qulonglong x = ui->analysisPlot->xAxis->pixelToCoord(event->pos().x());
    this->drawPlotTracer(x);
}

void ChannelChartForm::drawPlotTracer(qulonglong x)
{
    QCPGraph *mGraph = ui->dataPlot->graph(0);
    QCPGraph *mGraphResi = ui->analysisPlot->graph(0);

    QString time = QDateTime::fromSecsSinceEpoch(x).toString("yyyy-MM-dd HH:mm:ss");

    //将像素点转换成qcustomplot中的坐标值,并通过setGraphKey将锚点值设为真实数据值。tracer->setGraphKey(xAxis->pixelToCoord(event->pos().x()));

    //显示锚点
    tracer->setVisible(true);
    tracer->setGraph(mGraph);//将锚点设置到被选中的曲线上
    tracer->setGraphKey(x); //将游标横坐标设置成刚获得的横坐标数据x
    tracer->setInterpolating(false); //游标的纵坐标可以通过曲线数据线性插值自动获得
    tracer->updatePosition(); //使得刚设置游标的横纵坐标位置生效

    //显示锚点
    tracerResi->setVisible(true);
    tracerResi->setGraph(mGraphResi);//将锚点设置到被选中的曲线上
    tracerResi->setGraphKey(x); //将游标横坐标设置成刚获得的横坐标数据x
    tracerResi->setInterpolating(false); //游标的纵坐标可以通过曲线数据线性插值自动获得
    tracerResi->updatePosition(); //使得刚设置游标的横纵坐标位置生效

    double yValue = tracer->position->value();
    double yValueResi = tracerResi->position->value();

    QPoint pos((SettingConfig::getInstance().WINDOW_WIDTH - 500) / 2, -15);

    QString toolLabel = "时间:%1\r\n钟差(ns):%2\t残差(ns):%3";

    //显示tip框
    QToolTip::showText(pos, toolLabel.arg(time).arg(QString::number(yValue, 'f', 3)).arg(QString::number(yValueResi, 'f', 6)), this, this->rect(), 5*1000);

    //重绘
    ui->dataPlot->replot();
    ui->analysisPlot->replot();
}