QCustomPlot 重新绘制 QCPLayer

     2023-02-16     38

关键词:

【中文标题】QCustomPlot 重新绘制 QCPLayer【英文标题】:QCustomPlot replot QCPLayer 【发布时间】:2018-03-25 16:03:44 【问题描述】:

我正在尝试弄清楚如何使用 QCPLayer 仅重新绘制图中的某些项目。

qcustomplot documentation 声明如下:

如果你经常需要调用一个完整的 QCustomPlot::replot 只是因为一个非复杂对象(例如一个项目)发生了变化,而绘图中有相对静态但复杂的图形,请考虑将定期变化的对象放在自己的层上并将其模式 (QCPLayer::setMode) 设置为 QCPLayer::lmBuffered。这使得 QCustomPlot 为该层分配一个专用的绘制缓冲区,并允许使用 QCPLayer::replot 单独重新绘制它,独立于包含潜在复杂和缓慢图形的其他层。有关详细信息,请参阅相应方法的文档。

这是我在下面的示例中尝试做的事情:

我正在通过从QCustomPlot 继承来创建 custom qcustomplot:

QCustomPlot_custom.h

#pragma once
#include "qcustomplot.h"    
#define USING_LAYER false

struct QCPCursor
   QCPItemLine *hLine;
   QCPItemLine *vLine;
   QCPItemText* cursorText;
;

class QCustomPlot_custom :
   public QCustomPlot

   Q_OBJECT    
private slots:
   void mouseMove(QMouseEvent*);

public:
   QCustomPlot_custom(QWidget* parent = NULL);
   ~QCustomPlot_custom()
private:
   QCPLayer* cursorLayer;
   QCPCursor cursor;   
   void manageCursor(double x, double y, QPen pen);
public:
   void init(QVector<double> xdata, QVector<double> ydata);
;

这个类用一些要绘制的数据进行初始化。它还重载mouseMove 事件来控制自定义光标。 USING_LAYER 设置为true 表示自定义光标添加到它自己的层(cursorLayer)。

通过将 USING_LAYER 设置为 false,我得到了如下所示的预期效果:

光标由水平和垂直线和坐标显示。

如果我在图中有很多图表和/或每个图表中有很多点,我会在移动光标时看到延迟。 (这就是我希望能够通过将光标设置在图层中来仅重新绘制光标的原因。)

QCustomPlot_custom.cpp

QCustomPlot_custom::QCustomPlot_custom(QWidget* parent)

   connect(this, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMove(QMouseEvent*)));   
   QCustomPlot::setInteraction(QCP::iRangeDrag, true);
   QCustomPlot::setInteraction(QCP::iRangeZoom, true);
   if (USING_LAYER)
      this->addLayer("cursorLayer", 0, QCustomPlot::limAbove);
      cursorLayer = new QCPLayer(this, "cursorLayer");
      cursorLayer->setMode(QCPLayer::lmBuffered);
   


void QCustomPlot_custom::init(QVector<double> xdata, QVector<double> ydata)
   
   this->addGraph();
   this->graph(0)->setData(xdata, ydata);

   QColor colorPen(10, 25, 180, 255);
   QPen pen;
   pen.setWidth(50);
   pen.setColor(colorPen);
   this->graph()->setLineStyle(QCPGraph::lsLine);
   this->graph()->setPen(QPen(colorPen));
   this->xAxis->setLabel("X-axis");
   this->yAxis->setLabel("Y-axis");      
   this->rescaleAxes();
   this->replot();


void QCustomPlot_custom::mouseMove(QMouseEvent* event)

   //Cursor coordinates:
   double x = this->xAxis->pixelToCoord(event->pos().x());
   double y = this->yAxis->pixelToCoord(event->pos().y());
   manageCursor(x, y, QPen(Qt::DashDotLine));            
   if (USING_LAYER)
      cursorLayer->replot(); 
   else
      this->replot();


void QCustomPlot_custom::manageCursor(double x, double y, QPen pen)

   if (cursor.hLine)
      this->removeItem(cursor.hLine);
   cursor.hLine = new QCPItemLine(this);   
   cursor.hLine->setPen(pen);
   cursor.hLine->start->setCoords(-QCPRange::maxRange, y);
   cursor.hLine->end->setCoords(QCPRange::maxRange, y);

   if (cursor.vLine)
      this->removeItem(cursor.vLine);
   cursor.vLine = new QCPItemLine(this);   
   cursor.vLine->setPen(pen);
   cursor.vLine->start->setCoords(x, -QCPRange::maxRange);
   cursor.vLine->end->setCoords(x, QCPRange::maxRange);

   //Coordinates as text:   
   if (cursor.cursorText)
      this->removeItem(cursor.cursorText);
   cursor.cursorText = new QCPItemText(this);
   cursor.cursorText->setText(QString("(%1, %2)").arg(x).arg(y));
   cursor.cursorText->position->setCoords(QPointF(x, y));
   QPointF pp = cursor.cursorText->position->pixelPosition() + QPointF(50.0, -15.0);
   cursor.cursorText->position->setPixelPosition(pp);
   cursor.cursorText->setFont(QFont(font().family(), 8));

   //Add to layer:
   if (USING_LAYER)
      cursor.hLine->setLayer(cursorLayer); 
      cursor.vLine->setLayer(cursorLayer); 
      cursor.cursorText->setLayer(cursorLayer);
   

初始化类成员的函数:

void Qt_PlotTest::testPlot()
   //Create some data and initalize plot:
   QVector<double> yData, xData;
   int imax = 100000;
   for (int i = 0; i < imax; i++)
      double x = double(i) / imax;
      xData.push_back(x);
      yData.push_back(pow(x, 2)*( 1.0 + 0.5*cos(20*x) + 0.1*sin(500*x - 0.1)));
   
   ui.custom_QWidgetPlot->init(xData, yData);

使用 layer 方法时,光标不渲染。我尝试理解文档,但我不清楚如何正确使用QCPLayers。

我应该怎么做?

【问题讨论】:

【参考方案1】:

添加图层后

this->addLayer("cursorLayer", 0, QCustomPlot::limAbove);

不要调用QCPLayer 构造函数来获取层指针。使用提供的带有层或索引名称的 getter:

QCPLayer * QCustomPlot::layer ( const QString & name) const

QCPLayer * QCustomPlot::layer ( int index) const

cursorLayer = this->layer("cursorLayer");

还将每个 Graph 和 Item 添加到 currentLayer 中,在您的情况下,它不是 cursorLayer,而是 main。您需要更改当前图层

bool QCustomPlot::setCurrentLayer ( const QString & name)

bool QCustomPlot::setCurrentLayer ( QCPLayer * layer)

即:

this->setCurrentLayer("cursorLayer");
this->addGraph();
...
this->setCurrentLayer("main");

或者你可以为每个QCPLayerable指定层

bool QCPLayerable::setLayer ( QCPLayer * layer)

bool QCPLayerable::setLayer ( const QString & layerName)

someGraph->setLayer("cursorLayer);

【讨论】:

我试过cursorLayer = this-&gt;layer("cursorLayer");。在QCustomPlot_custom::manageCursor 中创建hlinevlinecursorText 之前,我还尝试了this-&gt;setCurrentLayer("cursorLayer");,并使用f.ex 将每个项目设置为图层。 hline-&gt;setLayer("cursorLayer);。现在发生的情况是,我的光标仅在我缩放或拖动视图时才会呈现(因为可能会调用 this-&gt;replot())。如果我调试并深入研究cursorLayer-&gt;replot(),我发现它失败了,因为bool QCustomPlot::hasInvalidatedPaintBuffers() 返回true 我不确定为什么要在每个 mouseMove(QMouseEvent* event) 之后删除并再次创建游标。在init中创建一次,然后在mouseMove中调用setCoords 我同意。该方法取自某处的不同示例。我只是想在更改之前解决此重新绘制问题。但是,如果我总是在重新创建光标后将其添加到图层中,它不应该对这个问题产生影响。但也许,我会仔细看看。【参考方案2】:

正如@EligijusPupeikis 提醒我的那样,我每次移动光标时都会删除并重新创建光标。

我认为这不会对我的问题产生任何影响,但显然确实如此,因为重新绘制包含新项目的图层需要先重新绘制绘图(来源:将检查 qcustomplot文档并添加链接)。

所以我的代码现在看起来像这样:

QCustomPlot_custom::QCustomPlot_custom(QWidget* parent)

   connect(this, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMove(QMouseEvent*)));   
   QCustomPlot::setInteraction(QCP::iRangeDrag, true);
   QCustomPlot::setInteraction(QCP::iRangeZoom, true);


void QCustomPlot_custom::init(QVector<double> xdata, QVector<double> ydata)
   
   this->addGraph();
   this->graph(0)->setData(xdata, ydata);

   QColor colorPen(10, 25, 180, 255);
   QPen pen;
   pen.setWidth(50);
   pen.setColor(colorPen);
   this->graph()->setLineStyle(QCPGraph::lsLine);
   this->graph()->setPen(QPen(colorPen));
   this->xAxis->setLabel("X-axis");
   this->yAxis->setLabel("Y-axis");      
   this->rescaleAxes();
   this->replot();

   if (USING_LAYER)
      this->addLayer("cursorLayer", 0, QCustomPlot::limAbove);
      cursorLayer = this->layer("cursorLayer");
      //cursorLayer = new QCPLayer(this, "cursorLayer");
      cursorLayer->setMode(QCPLayer::lmBuffered);
   

   //Cursor:
   QPen qpen = QPen(Qt::DashDotLine);
   cursor.hLine = new QCPItemLine(this);
   cursor.hLine->setPen(qpen);
   cursor.vLine = new QCPItemLine(this);
   cursor.vLine->setPen(qpen);
   cursor.cursorText = new QCPItemText(this);
   cursor.cursorText->setFont(QFont(font().family(), 8));

   //Add to layer:
   if (USING_LAYER)
      cursor.hLine->setLayer("cursorLayer");  //"cursorLayer"
      cursor.vLine->setLayer("cursorLayer");
      cursor.cursorText->setLayer("cursorLayer");
   



void QCustomPlot_custom::mouseMove(QMouseEvent* event)

   //Cursor coordinates:
   double x = this->xAxis->pixelToCoord(event->pos().x());
   double y = this->yAxis->pixelToCoord(event->pos().y());
   manageCursor(x, y);            
   if (USING_LAYER)
      this->layer("cursorLayer")->replot();
   else
      this->replot();


void QCustomPlot_custom::manageCursor(double x, double y)

   cursor.hLine->start->setCoords(-QCPRange::maxRange, y);
   cursor.hLine->end->setCoords(QCPRange::maxRange, y);

   cursor.vLine->start->setCoords(x, -QCPRange::maxRange);
   cursor.vLine->end->setCoords(x, QCPRange::maxRange);

   cursor.cursorText->setText(QString("(%1, %2)").arg(x).arg(y));
   cursor.cursorText->position->setCoords(QPointF(x, y));
   QPointF pp = cursor.cursorText->position->pixelPosition() + QPointF(50.0, -15.0);      
 cursor.cursorText->position->setPixelPosition(pp);

作为测试,如果我绘制 10 000 000 个点,并将 USING_LAYER 设置为 false,我会在移动鼠标时注意到光标明显滞后。将其设置为true 时,将导致平滑的光标移动。

【讨论】:

qcustomplot使用分享层(完结)

...总是想把1.3.2版本拿出来比较一下,这篇文章也不例外。QCustomPlot2.0.0beta版本比1.3.2release版本有一个很大的改进那就是分层绘制,所谓分层绘制就是把一张图分几张图来绘制,最后在把这分开的几张图统一绘制到一张图上,比如... 查看详情

qcustomplot(二):图形绘制基础

参考技术A本文为QCustomPlot官方教程的中文翻译版。本教程使用customPlot指针指向QCustomPlot实例。如果您在QtCreator中提升了一个小部件,可以通过ui->customPlot(或您为小部件指定的任何名称)访问相应的小部件。您可以通过customPlot... 查看详情

如何有效地使用 QCustomPlot 绘制大型时间序列?

】如何有效地使用QCustomPlot绘制大型时间序列?【英文标题】:HowtoplotlargetimeserieswithQCustomPlotefficiently?【发布时间】:2014-12-1107:44:52【问题描述】:我目前正在使用QCustomPlot在Qt中绘制数字信号,但似乎当样本数大于10000000时,操... 查看详情

qcustomplot使用——绘制折线图

//初始化数据QVector<double>temp;for(intvar=0;var<25;++var)if(rand()%2)temp.append(var);elsetemp.append(20);QVector<double>time;for(intvar=0;var<25;++var)time.appen 查看详情

使用qt绘图控件qcustomplot绘制波形图(代码片段)

...受到的数据通过曲线显示出来,其实这是用一个叫做QCustomPlot的控件,这个控件不是QT自带的,需要自己下载加入,今天介绍一下这个控件的使用方法,并附源码。QCustomPlot简介QCustomPlot是开源的Qt的第三方绘图... 查看详情

使用qt绘图控件qcustomplot绘制波形图(代码片段)

...受到的数据通过曲线显示出来,其实这是用一个叫做QCustomPlot的控件,这个控件不是QT自带的,需要自己下载加入,今天介绍一下这个控件的使用方法,并附源码。QCustomPlot简介QCustomPlot是开源的Qt的第三方绘图... 查看详情

QCustomPlot 海量数据绘图

】QCustomPlot海量数据绘图【英文标题】:QCustomPlotHugeAmountofDataPlotting【发布时间】:2017-03-1123:45:23【问题描述】:我正在尝试使用qcustomplot类在我的QtGui程序上绘制一些串行数据。当我尝试绘制100个数据/秒的低采样频率数据时,我... 查看详情

Qt5 QCustomPlot。实时大图

】Qt5QCustomPlot。实时大图【英文标题】:Qt5QCustomPlot.Largegraphinrealtime【发布时间】:2015-12-0913:00:07【问题描述】:我目前正在开发一个实时绘制来自ADC的数据的应用程序。在某些情况下,我必须绘制大约150k点,这需要一些时间。... 查看详情

qt使用qcustomplot绘制柱状图

...,  ui(newUi::ClgBar)  ui->setupUi(this);  QCustomPlot* m_rectPlot=newQCustomPlot;  ui->verticalLayout->addWidget(m_rectPlot);  m_rectPlot->xAxis->setLabel("参数");  m_rectPlot->yAxis->setLabel("个... 查看详情

基于qtquick的qcustomplot实现(代码片段)

...握必要的C++基础是学习和使用QtQuick框架的重要基石QCustomPlot能做什么可以在QWidget大放异彩,绘制各种图表和曲线也可以在QtQuick大展拳脚基于QtQuick的QCustomPlot实现继承QQuickPaintedItem类实现绘制效 查看详情

基于qtquick的qcustomplot实现(代码片段)

...握必要的C++基础是学习和使用QtQuick框架的重要基石QCustomPlot能做什么可以在QWidget大放异彩,绘制各种图表和曲线也可以在QtQuick大展拳脚基于QtQuick的QCustomPlot实现继承QQuickPaintedItem类实现绘制效 查看详情

qt使用qcustomplot绘制曲线例子

...(newUi::MainWindow)  ui->setupUi(this);  m_pPlot=newQCustomPlot;  m_pPlot->setInteractions(QCP::iRangeDrag|QCP::iRangeZoom|QCP::iMultiSelect|QCP::iSelectOther|QCP::iSelectItems);  m_pPlot->axisRect()->setupFullAxesBox();  m_pPlot->xAxi... 查看详情

qcustomplot学习使用分享

同时发布在http://blog.csdn.net/laixuepu/article/details/78825257QCustomplot学习使用分享QCustomplot网上和例子都是在资源和头文件中加入qcustomplot.h和qcustomplot.cpp,然后在.ui中添加Widget,然后提升为QCustomplot,然后重新命名,在mainwindow中调用,... 查看详情

qcustomplot(三):图形绘制基础之样式修改

参考技术A图形的外观由许多因素决定,所有这些因素都可以修改。以下是最重要的:轴的外观可以通过改变它们所用的笔和它们的标签使用的字体来修改。具体可以查看QCPAxis的文档。以下是最重要属性的快速摘要:setBasePen,setTi... 查看详情

如何改变 Qcustomplot 中曲线颜色相对于 x 轴的强度?

】如何改变Qcustomplot中曲线颜色相对于x轴的强度?【英文标题】:howtochangetheintensityofcurvecolourinQcustomplotwithrespecttox-axis?【发布时间】:2017-10-1202:58:36【问题描述】:我有一个问题,我必须绘制来自某个源的射线。在源处,强度应... 查看详情

QCustomPlot 在绘图调整大小期间出现错误

】QCustomPlot在绘图调整大小期间出现错误【英文标题】:QCustomPlotmisplotsduringplotresize【发布时间】:2015-09-0623:34:26【问题描述】:我有一个QCustomPlot正在绘制传入数据。这些图看起来很棒,但是当我突然调整窗口大小或缩放或拖动... 查看详情

qcustomplot基本使用(代码片段)

文章目录简述下载使用简述QCustomPlot是一个基于QtC++的图形库,用于绘制和数据可视化-制作漂亮的2D图-曲线图、趋势图、坐标图、柱状图等,并为实时可视化应用程序提供高性能服务。它没有进一步的依赖关系,... 查看详情

qt之qcustomplot(图形库)

简述QCustomPlot是一个基于QtC++的图形库,用于绘制和数据可视化-制作漂亮的2D图-曲线图、趋势图、坐标图、柱状图等,并为实时可视化应用程序提供高性能服务。它没有进一步的依赖关系,并有着良好的文档记... 查看详情