QCostomPlot 示例注解 3

Item

在QCustomPlot中,所有的Item都继承自QCPAbstractItem,QCustomPlot给我们提供了一些Item

在这里插入图片描述

item说明
QCPItemBracket括号Item
QCPItemCurve曲线Item,其实就是贝塞尔曲线
QCPItemEllipse椭圆/圆Item
QCPItemLine线段Item
QCPItemPixmap图片Item
QCPItemRect矩形Item
QCPItemStraightLine直线Item
QCPItemText文字Item
QCPItemTracer追踪者Item

QCPAbstractItem 默认存在于QCustomPlot的当前层中,默认的当前层为main,我们可以通过setClipToAxisRect和setClipAxisRect设置Item位于某个特定的轴矩形,将setClipToAxisRect设置为false则Item位于QCustomPlot

QCPItemAnchor与QCPItemPosition联系与区别

  1. QCPItemPosition继承自QCPItemAnchor
  2. QCPItemAnchor用于给QCPItemPosition定位用的
  3. QCPItemPosition则表示了Item的位置
  4. 一个Item可以有多个QCPItemAnchor和QCPItemPosition

我们主要理解QCPItemPosition是如何决定Item的位置的,它有四种位置类型:

ptAbsolute 按像素的方式
ptViewportRatio 按QCustomPlot可视区域的比例
ptAxisRectRatio 按其存在的轴矩形的比例(通过setAxisRect函数设置轴矩形)
ptPlotCoords 按坐标系位置(通过setAxes函数轴)
  1. 可以通过setType、setTypeX、setTypeY函数设置x、y方向的位置类型
  2. 通过setCoords设置其位置,setCoords是跟setType设置的类型相关的( 绝对位置 相对位置 )
  3. Item的位置还跟它锚定的父锚点QCPItemAnchor相关,可以通过setParentAnchor、setParentAnchorX、setParentAnchorY函数设置x、y方向的父锚点
bool QCPItemPosition::setParentAnchor(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
bool QCPItemPosition::setParentAnchorX(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
bool QCPItemPosition::setParentAnchorY(QCPItemAnchor *parentAnchor, bool keepPixelPosition)
  1. 父锚点决定了其起点位置,当设置父锚点后,type类型会变为ptAbsolute按绝对按像素的方式
  2. 我们可以直接通过setPixelPosition设置Item的像素位置,而不用管setType的类型是什么,通过pixelPosition返回Item的像素位置

QCPItemBracket 括号item

QCPItemBracket有四种类型:

  • bsSquare 中括号
  • bsRound 小括号
  • bsCurly 大括号
  • bsCalligraphic 实体大括号

通过left和right决定其位置,而center则用于给其它的QCPItemPosition定位用的

//  添加了一个括号item
  QCPItemBracket *bracket = new QCPItemBracket(customPlot);
  //设置一个起始点
  bracket->left->setCoords(3, 1.1);
//  设置一个中止点
  bracket->right->setCoords(13, 1.1);
//  设置括号长度
  bracket->setLength(10);
//  设置括号样式
  bracket->setStyle(QCPItemBracket::BracketStyle::bsRound);

QCPItemText

  1. 文字item有一个文字矩行
  2. plot有1个view矩形
  3. 1个Plot坐标轴矩形

QCPItemText由position决定其位置,但是position不一定是在文字中心的位置,我们可以通过setPositionAlignment设置position对齐在文字矩形的哪一个地方

//添加1个txt的item   add the text label at the top:
  QCPItemText *wavePacketText = new QCPItemText(customPlot);
//  设置父锚点,定位点
  wavePacketText->position->setParentAnchor(bracket->center);
//  设置相对父锚点坐标
  wavePacketText->position->setCoords(0, 1); // move 10 pixels to the top from bracket center anchor
//  设置txt的相对位置
  wavePacketText->setPositionAlignment(Qt::AlignBottom|Qt::AlignHCenter);
  //
  wavePacketText->setText("Wavepacket");
  //设置字体和大小
  wavePacketText->setFont(QFont(font().family(), 10));

QCPItemTracer

它主要用来跟踪QCPGraph的某个数据点,QCPItemTracer也是用一个position来决定其位置
实时跟踪的原理就是在定时器不断的设置key值

QCPItemTracer有五种风格

tsNone 不显示tracer
tsPlus 加号
tsCrosshair 十字线,横跨整个轴矩形
tsCircle 圆
tsSquare 方块
  1. QCPItemTracer通过函数setGraph和setGraphKey设置要跟踪的图表以及数据点,
  2. setGraph(nullptr)可以使QCPItemTracer得位置是任意的。
  3. QCPItemTracer的位置还跟setInterpolating函数有关,当setInterpolating为true时,启用线性插值,这时候QCPItemTracer的位置是精确地在我们设置的位置,并且对value轴的值进行线性插值;为false的时候QCPItemTracer的位置是最接近于这个位置的key值点的位置,就是自动获取value

效果图
在这里插入图片描述

void MainWindow::setupSimpleItemDemo(QCustomPlot *customPlot)
{
  demoName = "Simple Item Demo";
  customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);

  // add the text label at the top:
  QCPItemText *textLabel = new QCPItemText(customPlot);
  textLabel->setPositionAlignment(Qt::AlignTop | Qt::AlignHCenter);

  textLabel->position->setType(QCPItemPosition::ptAxisRectRatio);
  textLabel->position->setCoords(0.5, 0); // place position at center/top of axis rect
  textLabel->setText("Text Item Demo");
  textLabel->setFont(QFont(font().family(), 16)); // make font a bit larger
  textLabel->setPen(QPen(Qt::black));             // show black border around text

  // add the arrow:
  QCPItemLine *arrow = new QCPItemLine(customPlot);
  arrow->start->setParentAnchor(textLabel->bottom);
  arrow->end->setCoords(4, 1.6); // point to (4, 1.6) in x-y-plot coordinates
  //设置head为一个箭头
  arrow->setHead(QCPLineEnding::esSpikeArrow);
}

void MainWindow::setupItemDemo(QCustomPlot *customPlot)
{
  demoName = "Item Demo";
  //  可以缩放和拖动
  customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);

  QCPGraph *graph = customPlot->addGraph();
  int n = 200;
  double phase = 0;
  double k = 3;
  QVector<double> x(n), y(n);
  for (int i = 0; i < n; ++i)
  {
    //    x[i] = i/(double)(n-1)*34 - 17;
    //    y[i] = qExp(-x[i]*x[i]/20.0)*qSin(k*x[i]+phase);
    x[i] = i * 0.1;
    y[i] = qSin(x[i] * 3.15);
  }
  graph->setData(x, y);
  graph->setPen(QPen(Qt::blue));
  graph->rescaleKeyAxis();
  customPlot->yAxis->setRange(-1.45, 1.65);
  customPlot->xAxis->grid()->setZeroLinePen(Qt::NoPen);

  // add the bracket at the top:
  //  添加了一个括号item
  QCPItemBracket *bracket = new QCPItemBracket(customPlot);
  //设置一个起始点
  bracket->left->setCoords(3, 1.1);
  //  设置一个中止点
  bracket->right->setCoords(13, 1.1);
  //  设置括号长度
  bracket->setLength(10);
  //  设置括号样式
  bracket->setStyle(QCPItemBracket::BracketStyle::bsRound);

  //添加1个txt的item   add the text label at the top:
  QCPItemText *wavePacketText = new QCPItemText(customPlot);
  //  设置父锚点,定位点
  wavePacketText->position->setParentAnchor(bracket->center);
  //  设置相对父锚点坐标
  wavePacketText->position->setCoords(0, 1); // move 10 pixels to the top from bracket center anchor
                                             //  设置txt的相对位置
  wavePacketText->setPositionAlignment(Qt::AlignBottom | Qt::AlignHCenter);
  wavePacketText->setText("Wavepacket");
  wavePacketText->setFont(QFont(font().family(), 10));

  // add the phase tracer (red circle) which sticks to the graph data (and gets updated in bracketDataSlot by timer event):
  QCPItemTracer *phaseTracer = new QCPItemTracer(customPlot);
  itemDemoPhaseTracer = phaseTracer; // so we can access it later in the bracketDataSlot for animation
                                     //  设置待跟踪的graph
  phaseTracer->setGraph(graph);
  //  待跟踪的key
  phaseTracer->setGraphKey(M_PI);
  //  启用插值跟踪,也就是自动计算value
  phaseTracer->setInterpolating(true);
  //  设置跟踪点样式
  //  phaseTracer->setStyle(QCPItemTracer::tsCircle);
  phaseTracer->setStyle(QCPItemTracer::tsSquare);
  //  设置跟踪点的颜色
  phaseTracer->setPen(QPen(Qt::red));
  //  设置跟踪点的颜色
  phaseTracer->setBrush(Qt::red);
  phaseTracer->setSize(10);
  phaseTracer->setClipAxisRect(customPlot->axisRect());
  //  phaseTracer->
  //   phaseTracer->position->setType(QCPItemPosition::PositionType::ptPlotCoords);
  //  phaseTracer->position->setCoords(15 ,5);

  //  phaseTracer->setClipAxisRect()

  // add label for phase tracer:
  QCPItemText *phaseTracerText = new QCPItemText(customPlot);
  //设置左边点的参考方式
  phaseTracerText->position->setType(QCPItemPosition::ptAxisRectRatio);
  //  设置文字矩形相对于轴矩形或参考矩的位置
  phaseTracerText->setPositionAlignment(Qt::AlignRight | Qt::AlignBottom);
  //  文字矩形相对于参考矩形的位置
  phaseTracerText->position->setCoords(1, 0.9); // lower right corner of axis rect
  phaseTracerText->setText("Points of fixed\nphase define\nphase velocity vp");
  //   设置txt在文字矩形内的对齐方式
  phaseTracerText->setTextAlignment(Qt::AlignRight);
  //  文字的字体设置
  phaseTracerText->setFont(QFont(font().family(), 9));
  phaseTracerText->setPadding(QMargins(5, 5, 5, 5));
  
  //文字矩行背景
  phaseTracerText->setBrush(QColor(200, 80, 80, 100));
  //轴矩形背景色设置
  customPlot->axisRect()->setBackground(QColor(0, 100, 180, 200));
  //设置plot view 的矩形框背景色
  customPlot->setBackground(QColor(100, 200, 180));

  /*
   * 三阶贝塞尔曲线 QCPItemCurve  https://www.jianshu.com/p/0c9b4b681724
    start  曲线的起始点
    end    曲线的结束点
    startDir 控制曲线的曲率点1
    endDir  控制曲线曲率的点2

    */
  // 创建一个指向追踪器的箭头 add arrow pointing at phase tracer, coming from label:
  QCPItemCurve *phaseTracerArrow = new QCPItemCurve(customPlot);
  phaseTracerArrow->start->setParentAnchor(phaseTracerText->left);
  phaseTracerArrow->startDir->setParentAnchor(phaseTracerArrow->start);
  phaseTracerArrow->startDir->setCoords(-80, 0); // direction 30 pixels to the left of parent anchor (tracerArrow->start)
  //结束点始终追踪Tracer 实现动态追踪的效果
  phaseTracerArrow->end->setParentAnchor(phaseTracer->position);
  phaseTracerArrow->end->setCoords(10, 10);
  phaseTracerArrow->endDir->setParentAnchor(phaseTracerArrow->end);
  phaseTracerArrow->endDir->setCoords(120, 80);
  //  设置结束点形状
  phaseTracerArrow->setHead(QCPLineEnding::esSpikeArrow);
  //  QCPLineEnding(EndingStyle style, double width=8, double length=10, bool inverted=false);
  //  设置贝塞尔曲线的首 尾形状
  phaseTracerArrow->setTail(QCPLineEnding(QCPLineEnding::esBar, phaseTracerText->bottom->pixelPosition().y() - phaseTracerText->top->pixelPosition().y()));

  /******************************************************************************************************************/
  //创建一个跟踪器 add the group velocity tracer (green circle):
  QCPItemTracer *groupTracer = new QCPItemTracer(customPlot);
  groupTracer->setGraph(graph);
  groupTracer->setGraphKey(5.5);
  //  启用插值跟踪,也就是自动计算value
  groupTracer->setInterpolating(true);
  //  设置跟踪器的形状
  groupTracer->setStyle(QCPItemTracer::tsCircle);
  //  设置跟踪器的轮廓颜色
  groupTracer->setPen(QPen(Qt::red));
  //  设置跟踪器的填充颜色
  groupTracer->setBrush(Qt::green);
  //  设置跟踪器的大小
  groupTracer->setSize(15);

  //创建一个文本的item  add label for group tracer:
  QCPItemText *groupTracerText = new QCPItemText(customPlot);
//  设置文本的位置坐标的参考取值方式,相对于坐标轴矩形
  groupTracerText->position->setType(QCPItemPosition::ptAxisRectRatio);
//  文本矩形相对于plot矩形的位置
  groupTracerText->setPositionAlignment(Qt::AlignRight | Qt::AlignTop);
  //具体相对于plot矩形的位置,设置位置系数
  groupTracerText->position->setCoords(1, 0.01); // lower right corner of axis rect
//  设置内容
  groupTracerText->setText("Fixed positions in\nwave packet define\ngroup velocity vg");
//  设置相对于TXT矩形内的文字排列方式
  groupTracerText->setTextAlignment(Qt::AlignLeft);
//  设置字体和大小
  groupTracerText->setFont(QFont(font().family(), 9));
//设置 相对于txt矩形边框的间距
  groupTracerText->setPadding(QMargins(10, 0, 0, 0));

  // add arrow pointing at group tracer, coming from label:
  QCPItemCurve *groupTracerArrow = new QCPItemCurve(customPlot);

  groupTracerArrow->start->setParentAnchor(groupTracerText->left);
  groupTracerArrow->startDir->setParentAnchor(groupTracerArrow->start);
//  设置相对于父锚点的绝对像素位置
  groupTracerArrow->startDir->setCoords(-50, 100); // direction 30 pixels to the left of parent anchor (tracerArrow->start)
  groupTracerArrow->endDir->setParentAnchor(groupTracer->position);
  groupTracerArrow->endDir->setCoords(50, -200);
  groupTracerArrow->end->setParentAnchor(groupTracer->position);
  groupTracerArrow->end->setCoords(5, -10);

  groupTracerArrow->setHead(QCPLineEnding::esSpikeArrow);
  groupTracerArrow->setTail(QCPLineEnding(QCPLineEnding::esBar, (groupTracerText->bottom->pixelPosition().y() - groupTracerText->top->pixelPosition().y()) * 0.85));

  // add dispersion arrow:
  QCPItemCurve *arrow = new QCPItemCurve(customPlot);
  arrow->start->setCoords(1, 1);
  arrow->startDir->setCoords(1.2, 1.3);
  arrow->endDir->setCoords(5, 0.3);
  arrow->end->setCoords(10, 0.5);
  arrow->setHead(QCPLineEnding::esSpikeArrow);
  arrow->setPen(QPen(Qt::blue));

  // add the dispersion arrow label:
  QCPItemText *dispersionText = new QCPItemText(customPlot);
  dispersionText->position->setType(QCPItemPosition::PositionType::ptAxisRectRatio);
  dispersionText->position->setCoords(0.15, 0.15);
  dispersionText->setTextAlignment(Qt::AlignLeft);
  dispersionText->setRotation(10);
  dispersionText->setText("Dispersion with\nvp < vg");
  dispersionText->setFont(QFont(font().family(), 10));

  // setup a timer that repeatedly calls MainWindow::bracketDataSlot:
//  使用定时器不点切换key值实现动态跟踪效果
  connect(&dataTimer, SIGNAL(timeout()), this, SLOT(bracketDataSlot()));
  dataTimer.start(0); // Interval 0 means to refresh as fast as possible
}

动态切换效果

void MainWindow::realtimeDataSlot()
{
  static QTime timeStart = QTime::currentTime();
  // calculate two new data points:
  double key = timeStart.msecsTo(QTime::currentTime()) / 1000.0; // time elapsed since start of demo, in seconds
  static double lastPointKey = 0;
  if (key - lastPointKey > 0.002) // at most add point every 2 ms
  {
    // add data to lines:
    //      定时器循环添加数据
    ui->customPlot->graph(0)->addData(key, qSin(key) + std::rand() / (double)RAND_MAX * 1 * qSin(key / 0.3843));
    ui->customPlot->graph(1)->addData(key, qCos(key) + std::rand() / (double)RAND_MAX * 0.5 * qSin(key / 0.4364));
    // rescale value (vertical) axis to fit the current data:
    //ui->customPlot->graph(0)->rescaleValueAxis();
    //ui->customPlot->graph(1)->rescaleValueAxis(true);
    lastPointKey = key;
  }
  // make key axis range scroll with the data (at a constant range size of 8):
  //  自动更新坐标轴范围保证只是显示一部分内容
  ui->customPlot->xAxis->setRange(key, 8, Qt::AlignRight);
  //   ui->customPlot->rescaleAxes();
  ui->customPlot->replot();

  // calculate frames per second:
  //  状态栏更新统计数据
  static double lastFpsKey;
  static int frameCount;
  ++frameCount;
  if (key - lastFpsKey > 2) // average fps over 2 seconds
  {
    ui->statusBar->showMessage(
        QString("%1 FPS, Total Data points: %2")
            .arg(frameCount / (key - lastFpsKey), 0, 'f', 0)
            .arg(ui->customPlot->graph(0)->data()->size() + ui->customPlot->graph(1)->data()->size()),
        0);
    lastFpsKey = key;
    frameCount = 0;
  }
}
  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Car12

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值