QCustomPlot 实时曲线,坐标显示

环境

Qt 5.4.2
QCustomPlot

功能

1.X:时间, Y:实时数据, 鼠标移动显示坐标点
2.实时显示曲线,可更改曲线颜色,可隐藏/显示曲线

源码

1.下载QCustomPlot,将源码添加到项目中
在这里插入图片描述
2.修改Pro文件
在这里插入图片描述
3.CustomChart 源码

CustomChart.h

struct Point    //坐标点
{
   QString sX;
   double  dX;
   double  dY;
   Point(){
     sX="";
     dX=0;
     dY=0;
  }
};

struct Line                     //曲线
{
    QString sName;             //曲线名称
    QList<Point> tPoints;      //坐标
    Line()
    {
        sName = "";
        tPoints.clear();
    }
};

namespace Ui { class CustomChart; }
class ChartCheckBox;

class CustomChart : public QMainWindow
{
    Q_OBJECT
public:
    explicit CustomChart(QWidget *parent = 0);
    ~CustomChart();
private:
    Ui::CustomChart *ui;
private:
    QCustomPlot *pCustomPlot;
    QList<Line> tLineArray;            //曲线点
    QList<ChartCheckBox *> checkArray; //曲线

    QLabel *pLabel;                    //鼠标移动显示坐标
    QWidget *pScrollWidget;
    QVBoxLayout *pVBoxLayout;

    double dLower;                      //X轴范围
    double dUpper;
public:
    int AddLine(QString lineName);
    int DelLine(QString lineName);
    int AddPoint(QString lineName,Point point);
    int ClearLine();
private:
    void InitCustomChart();
private slots:
    void CheckBoxStateChanged(int identify,int state);
    void CheckBoxColorChanged(int identify,QColor color);
    void ChartMouseMove(QMouseEvent *event);
    void SelecetChanged(int state);
};
class ChartCheckBox:public QCheckBox
{
    Q_OBJECT
public:
    explicit ChartCheckBox(){installEventFilter(this); }
    explicit ChartCheckBox(const QString &text){this->setText(text); installEventFilter(this);}
    ~ChartCheckBox(){}
protected:
    bool eventFilter(QObject *obj, QEvent *event)    //Change Color
    {
        if(obj == this && event->type() == QEvent::MouseButtonPress)
        {
            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            if (mouseEvent->button() == Qt::RightButton)
            {
              QColorDialog colorDialog;
              QColor selectedColor = colorDialog.getColor(Qt::red,NULL,this->text());
              if(selectedColor.isValid())
              {
                 setStyleSheet(QString("QCheckBox { color: %1; }").arg(selectedColor.name()));
                 emit  changeColors(nIdentify,selectedColor);
              }
              return true;
            }
        }
        return QCheckBox::eventFilter(obj, event);
    }
public:
    void SetIdentify(int nindex)
    {
        nIdentify = nindex;
        connect(this,SIGNAL(stateChanged(int)),this,SLOT(slot_stateChanged(int)));
    }
signals:
    void stateSignals(int identify,int state);
    void changeColors(int identify,QColor color);
private slots:
    void slot_stateChanged(int state){emit stateSignals(nIdentify,state);}
private:
    int nIdentify;
};

CustomChart.cpp:

CustomChart::CustomChart(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::CustomChart)
{
    ui->setupUi(this);
    InitCustomChart();
}
CustomChart::~CustomChart()
{
    delete ui;
}

int CustomChart::AddLine(QString lineName)
{
      int ColorR = rand()%210;
      int ColorG = rand()%210;
      int ColorB = rand()%210;

      Line tLine;

      tLine.sName = lineName;
      tLine.tPoints.clear();
      tLineArray.append(tLine);

      ui->WChart->addGraph();
      ui->WChart->graph(tLineArray.count()-1)->setPen(QPen(QColor(ColorR,ColorG,ColorB)));
      ui->WChart->graph(tLineArray.count()-1)->setName(lineName);


      if(1 == tLineArray.count())
      {
         QCheckBox *checkBox= new QCheckBox();
         checkBox->setText("全选/全不选");
         checkBox->setChecked(true);
         pVBoxLayout->addWidget(checkBox);

         connect(checkBox,SIGNAL(stateChanged(int)),this,SLOT(SelecetChanged(int)));
       }

        ChartCheckBox *cbxChart=new ChartCheckBox();
        pVBoxLayout->addWidget(cbxChart);


        cbxChart->setText(lineName);         //曲线名
        cbxChart->setCheckState(Qt::Checked); //设置checkBox状态为勾选状态
        cbxChart->SetIdentify(tLineArray.count()-1);
        cbxChart->setStyleSheet("color: rgb("+QString::number(ColorR)+ ","+QString::number(ColorG)+ ","+QString::number(ColorB) +");");
        connect(cbxChart, SIGNAL(stateSignals(int,int)), this, SLOT(CheckBoxStateChanged(int,int)));
        connect(cbxChart, SIGNAL(changeColors(int,QColor)), this, SLOT(CheckBoxColorChanged(int,QColor)));
        checkArray.append(cbxChart);
        return 0;
}
int CustomChart::DelLine(QString lineName)
{
    for(int i=0; i<tLineArray.count();i++)
    {
        if(lineName == tLineArray[i].sName)
        {
            tLineArray.removeAt(i);
            ui->WChart->removeGraph(ui->WChart->graph(i));
            QLayoutItem *pLayoutItem;
            QWidget *pLayoutWidget;
            ChartCheckBox *pLayoutCheck;
            for (int i = 0; i < pVBoxLayout->count(); i++)
            {
                pLayoutItem = pVBoxLayout->itemAt(i);
                pLayoutWidget = pLayoutItem->widget();
                pLayoutCheck = qobject_cast<ChartCheckBox*>(pLayoutWidget);
                if(pLayoutCheck)
                {
                    if(lineName == pLayoutCheck->text())
                    {
                        delete pLayoutWidget;
                    }
                }
             }
            return 0;
        }
    }
    ui->WChart->replot();
    return -1;
}
int CustomChart::AddPoint(QString lineName, Point point)
{
    for(int i=0; i<tLineArray.count(); i++)
    {
        if(lineName == tLineArray[i].sName)
        {
            tLineArray[i].tPoints.append(point);
            ui->WChart->graph(i)->addData(point.dX,point.dY);
            qint64 milliseconds = qint64(point.dX * 1000.0);
            QDateTime currentDateTime = QDateTime::fromMSecsSinceEpoch(milliseconds);
            double upper = (double)(currentDateTime.toMSecsSinceEpoch() / 1000.0);
            //不丢失数据,继续加载数据,修改X轴范围区间
            if(dUpper <= upper)
            {
                dUpper = (double)(currentDateTime.addSecs(60).toMSecsSinceEpoch() / 1000.0);;
                ui->WChart->xAxis->setRange(dLower,dUpper);
            }
            ui->WChart->replot();
            return 0;
        }
    }
    return -1;
}

int CustomChart::ClearLine()
{
    tLineArray.clear();
    ui->WChart->clearGraphs();
    checkArray.clear();
    QLayoutItem *child;

    while ((child = pVBoxLayout->takeAt(0)) != NULL)
    {
        delete child->widget();
        delete child;
    }
    return 0;
}

void CustomChart::InitCustomChart()
{
    tLineArray.clear();
    checkArray.clear();

    pVBoxLayout =new QVBoxLayout(ui->WLine);
    pVBoxLayout->setMargin(5);

    ui->WLine->setLayout(pVBoxLayout);
    pCustomPlot = ui->WChart;

    ui->WChart->xAxis->setLabel("");
    ui->WChart->yAxis->setLabel("");

    QSharedPointer<QCPAxisTickerDateTime> dateTicker(new QCPAxisTickerDateTime);  //日期做X轴
    dateTicker->setDateTimeFormat("yyyy-MM-dd\nhh:mm:ss");//日期格式(可参考QDateTime::fromString()函数)

    ui->WChart->xAxis->setTicker(dateTicker);//设置X轴为时间轴
    ui->WChart->xAxis->setTickLabelRotation(35);//设置角度
    ui->WChart->xAxis->setTickLabels(false);//显示刻度标签
    ui->WChart->setInteractions(QCP::iRangeDrag          //可平移
                                | QCP::iRangeZoom        //可轮缩放
                                | QCP::iSelectLegend );  //可选中图例

    pCustomPlot->yAxis->setRange(0,110);
    
    dLower = (double)(QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0);
    dUpper = (double)(QDateTime::currentDateTime().addSecs(300).toMSecsSinceEpoch() / 1000.0);
    ui->WChart->xAxis->setRange(dLower,dUpper);

    //创建一个标签用于显示坐标
    pLabel = new QLabel(ui->WChart);
    pLabel->setVisible(false);
    connect(pCustomPlot,SIGNAL(mouseMove(QMouseEvent*)),this,SLOT(ChartMouseMove(QMouseEvent*)));
}

void CustomChart::CheckBoxStateChanged(int identify, int state)
{
    if(state!=0)
    {
        //显示
        ui->WChart->graph(identify)->setVisible(true);
    }else{
        //隐藏
        ui->WChart->graph(identify)->setVisible(false);
    }
    ui->WChart->replot();
}

void CustomChart::CheckBoxColorChanged(int identify, QColor color)
{
    ui->WChart->graph(identify)->setPen(QPen(color));
    ui->WChart->replot();
}
void CustomChart::ChartMouseMove(QMouseEvent *event)
{
    double x = ui->WChart->xAxis->pixelToCoord(event->pos().x());
    double y = ui->WChart->yAxis->pixelToCoord(event->pos().y());
    QPoint pos = event->pos();
    QCPAbstractPlottable *plottable = ui->WChart->plottableAt(pos);
    if(plottable)
    {
         QCPGraph *graph = qobject_cast<QCPGraph*>(plottable);
         int dataIndex = graph->selectTest(pos, false);
         if(dataIndex == -1)   {  pLabel->setVisible(false); return; }
         if(!graph->visible()) {  pLabel->setVisible(false);  return; }
         qint64 milliseconds = qint64(x * 1000.0);
         QDateTime currentDateTime = QDateTime::fromMSecsSinceEpoch(milliseconds);
         QString sDateTime = currentDateTime.toString("yyyy-MM-dd hh:mm:ss");
         pLabel->setText(graph->name() + "\n"+QString("x: %1\ny: %2").arg(sDateTime).arg(y));
         pLabel->move(event->x()+5,event->y());
         pLabel->setVisible(true);
         return;
     }
      pLabel->setVisible(false);
}


void CustomChart::SelecetChanged(int state)
{
    if(state != 0) //全部显示
    {
        for(int i=0; i<checkArray.count(); i++)
        {
            checkArray[i]->setChecked(true);
        }
    }else{         //全部取消
        for(int i=0; i<checkArray.count(); i++)
        {
            checkArray[i]->setChecked(false);
        }
    }
}

3.mainWindow 源码

mainWindow.h

#include "customchart.h"
namespace Ui {class MainWindow;}

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
private:
    Ui::MainWindow *ui;
private:
    QTimer *pFlushTimer;
    CustomChart *pCustomChart;
private:
     void InitFlushTime();
private slots:
     void on_flushTimerOut();
};

mainWindow.cpp

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

    pCustomChart = new CustomChart();
    QGridLayout *layout = new QGridLayout();
    layout->addWidget(pCustomChart);
    ui->widget->setLayout(layout);
    for(int i=0; i<10; i++)
    {
        pCustomChart->AddLine("Line "+QString::number(i));
    }
    InitFlushTime();
}
void MainWindow::InitFlushTime()
{
    pFlushTimer = new QTimer();
    pFlushTimer->setInterval(1000);
    pFlushTimer->start();
    connect(pFlushTimer,SIGNAL(timeout()),this,SLOT(on_flushTimerOut()));
}

void MainWindow::on_flushTimerOut()
{
   Point point;
   for(int i=0; i<10; i++)
   {
       point.sX = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
       point.dX = (double)(QDateTime::currentDateTime().toMSecsSinceEpoch()/1000.0);
       point.dY = qrand()% 10 + i*10;
       pCustomChart->AddPoint("Line "+QString::number(i),point);
   }
}

运行

运行结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QCustomPlot是一个开源的Qt绘图库,它可以用于在应用程序中绘制各种图表和图形。 要在QCustomPlot显示曲线坐标点值,我们可以使用以下步骤: 1. 创建一个QCustomPlot对象: ``` QCustomPlot *customPlot = new QCustomPlot(); ``` 2. 创建一个QCPGraph对象,并将其添加到QCustomPlot中: ``` QCPGraph *graph = customPlot->addGraph(); ``` 3. 设置曲线的数据点: ``` QVector<double> xData, yData; // 假设这里有x和y坐标数据 // 将数据点添加到xData和yData中 graph->setData(xData, yData); ``` 4. 启用坐标点值显示功能: ``` customPlot->setInteraction(QCP::iSelectPlottables); // 允许选择绘图组件 customPlot->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical); // 允许拖动坐标轴范围 customPlot->axisRect()->setRangeZoom(Qt::Horizontal | Qt::Vertical); // 允许缩放坐标轴范围 graph->setSelectable(QCP::stSingleData); // 允许选择单个数据点 ``` 5. 实现槽函数来响应数据点的选择事件,在槽函数中获取选择的数据点坐标值并显示: ``` QObject::connect(customPlot, &QCustomPlot::plottableClick, this, [=](QCPAbstractPlottable *plottable, int dataIndex) { if (plottable == graph) { double x = xData[dataIndex]; double y = yData[dataIndex]; // 将坐标显示到UI中 } }); ``` 通过上述步骤,我们可以在QCustomPlot显示曲线坐标点值。当用户点击曲线上的数据点时,我们可以获得选择的数据点的坐标值,并将其显示到用户界面上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值