QCustomplot 层 (七)

2024-05-10 06:38
文章标签 qcustomplot

本文主要是介绍QCustomplot 层 (七),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、分层绘制

    一直说要讲2.0.0版本,但总是想把1.3.2版本拿出来比较一下,这篇文章也不例外。QCustomPlot2.0.0beta版本比1.3.2release版本有一个很大的改进那就是分层绘制,所谓分层绘制就是把一张图分几张图来绘制,最后在把这分开的几张图统一绘制到一张图上,比如一张图A,需要分开成3张图B、C和D来绘制,当图A需要重新绘制时,我们一次判断B、C和D是否需要重新绘制,如果不需要绘制的我们直接把图贴到A上,那就很大的减少了重新绘制的时间,而这部分时间其实是没有必要花费的。

二、QCustomPlot的层

    QCustomPlot默认提供了6个层,如下代码所示,分别是:背景层、网格层、主层、坐标轴层、图例层和矩形选择区域层。

1 mLayers.append(new QCPLayer(this, QLatin1String("background")));
2 mLayers.append(new QCPLayer(this, QLatin1String("grid")));
3 mLayers.append(new QCPLayer(this, QLatin1String("main")));
4 mLayers.append(new QCPLayer(this, QLatin1String("axes")));
5 mLayers.append(new QCPLayer(this, QLatin1String("legend")));
6 mLayers.append(new QCPLayer(this, QLatin1String("overlay")));
  • 背景层:绘制背景图
  • 网格层:绘制网格线,每一个坐标轴对应一个网格对象
  • 主层:绘制图表
  • 坐标轴层:绘制坐标轴
  • 图例层:绘制图例
  • overlay层:绘制最上层的东西,这一层在1.3.2版本时没有。鼠标选择矩形框在此层绘制。可以参考第五篇文章中图1

    实现分层绘制的关键类QCPAbstractPaintBuffer,这是一个抽象基类,通过该类可以拿到一个QCPPainter指针,然后绘制东西的时候,都会绘制在这个指针所指的绘图设备上。QCPAbstractPaintBuffer类一共有3个子类,分别是QCPPaintBufferPixmap、QCPPaintBufferGlPbuffer和QCPPaintBufferGlFbo,这3个类分别使用了不同绘图技术来实现分层绘制。默认使用的是QCPPaintBufferPixmap来绘制,如果想使用QCPPaintBufferGlPbuffer或者QCPPaintBufferGlFbo来绘制,首先要使用setOpenGl接口打开使用opengl开关,然后定义QCP_OPENGL_FBO宏来默认使用QCPPaintBufferGlFbo绘制,或者定义QCP_OPENGL_PBUFFER宏来让默认使用QCPPaintBufferGlPbuffer方式绘制

三、QCPLayer

    下图所示是QCPLayer图层类的部分头文件,代码里的大多数成员变量和成员方法我都给出了注释,大家看看并仔细揣摩一下,应该就基本能理解了。

class QCP_LIB_DECL QCPLayer : public QObject
{
    enum LayerMode {//分层绘制原理
        lmLogical   ///< Layer is used only for rendering order, and shares paint buffer with all other adjacent logical layers.
        , lmBuffered ///< Layer has its own paint buffer and may be replotted individually (see \ref replot).
    };

    QCPLayer(QCustomPlot* parentPlot, const QString &layerName);
    virtual ~QCPLayer();

    // setters:
    void setVisible(bool visible);//设置层是否可见
    void setMode(LayerMode mode);//绘制时,painter使用模式

    // non-virtual methods:
    void replot();//重新绘制层

protected:
    QCustomPlot *mParentPlot;//所在图表
    QString mName;//层名称
    int mIndex;//层序,决定绘制先后顺序
    QList<QCPLayerable*> mChildren;//层中所有元素
    bool mVisible;//是否可见标记
    LayerMode mMode;//绘制模式标记

    // non-property members:
    QWeakPointer<QCPAbstractPaintBuffer> mPaintBuffer;//绘制缓冲区

    // non-virtual methods:
    void draw(QCPPainter *painter);//使用painter绘制
    void drawToPaintBuffer();//绘制到缓冲区
    void addChild(QCPLayerable *layerable, bool prepend);//新增元素
    void removeChild(QCPLayerable *layerable);//移除元素
};

四、自定义层

    如图1中所示的黑色十字线,就是我在自定义层中绘制的,下面我将我实现的代码贴出来

图1

    实现头文件

class CrossLinePlot : public  QCPLayerable
{
    Q_OBJECT
signals :
    void DrawCrossLine(const QPoint & pos);

public:
    CrossLinePlot(PlotCallback * basePlot, QCustomPlot * plot);
    ~CrossLinePlot();

public:
    QString LayerName() const;//层名称
    void SetVisible(bool visible);//设置层是否绘制

    void SetPen(const QPen & pen);/设置十字线画笔

    bool MouseButtonDown() const ;
    bool GetLineVisible(QCP::LineState line) const;
    void SetLineShow(QCP::LineState lines);//设置线是否显示

    //十字线同步注册接口
    bool RegisiterBortherLine(CrossLinePlot * line);
    bool UnregisiterBortherLine(CrossLinePlot * line);

protected:
    virtual void applyDefaultAntialiasingHint(QCPPainter *painter) const{};
    virtual void draw(QCPPainter * painter);

private:
    void DrawLine(QCPAxis * axis, Qt::Orientation orientation);//画指定方向的坐标轴十字线(严格来说应该是一部分,一条线)
    void SyncLinePosition(const QPoint & pos, double x);//同步线位置

private slots:
    void MouseMoveHandle(QMouseEvent * event);

private:
    QScopedPointer<CrossLinePlotPrivate> d_ptr;
    static std::vector<CrossLinePlot *> m_BrotherLine;//同步其他十字线
};

 

    实现文件

 

std::vector<CrossLinePlot *>CrossLinePlot::m_BrotherLine;

struct CrossLinePlotPrivate
{
    QCP::LineStates m_bIsVisible;
    bool m_bLeftButtonPress = false;
    double m_dAxisXValue = -1;
    QPoint m_MousePoint;
    QCPPainter * m_pPainter = nullptr;
    QPen m_Pen = QPen(Qt::black, 1, Qt::DashDotLine);
    PlotCallback * m_pParentPlot = nullptr;
};

CrossLinePlot::CrossLinePlot(PlotCallback * basePlot, QCustomPlot * plot)
    : QCPLayerable(plot)
    , d_ptr(new CrossLinePlotPrivate)
{
    d_ptr->m_pParentPlot = basePlot;
    mParentPlot->addLayer(LayerName());

    setLayer(LayerName());

    connect(mParentPlot, &QCustomPlot::mousePress, this, [this](QMouseEvent * event){
        if (event->button() & Qt::LeftButton)
        {
            d_ptr->m_bLeftButtonPress = true;
        }
    });
    connect(mParentPlot, &QCustomPlot::mouseRelease, this, [this](QMouseEvent * event){
        if (event->button() & Qt::LeftButton)
        {
            d_ptr->m_bLeftButtonPress = false;
        }
    });
    connect(mParentPlot, &QCustomPlot::mouseMove, this, &CrossLinePlot::MouseMoveHandle);

    QVector<qreal> dashes;
    qreal space = 4;
    dashes << 3 << space << 9 << space;
    d_ptr->m_Pen.setDashPattern(dashes);
}

CrossLinePlot::~CrossLinePlot()
{

}

QString CrossLinePlot::LayerName() const
{
    return QStringLiteral("crossline");
}

void CrossLinePlot::SetVisible(bool visible)
{
    QCPLayer * layer = mParentPlot->layer(LayerName());
    if (layer)
    {
        layer->setVisible(visible);
    }
}

void CrossLinePlot::SetPen(const QPen & pen)
{
    d_ptr->m_Pen = pen;
}

bool CrossLinePlot::MouseButtonDown() const
{
    return d_ptr->m_bLeftButtonPress;
}

bool CrossLinePlot::GetLineVisible(QCP::LineState line) const
{
    switch (line)
    {
    case Qt::Horizontal:
        return d_ptr->m_bIsVisible.testFlag(QCP::E_Horizontal);
        break;
    case Qt::Vertical:
        return d_ptr->m_bIsVisible.testFlag(QCP::E_Vertical);
        break;
    }

    return false;
}

void CrossLinePlot::SetLineShow(QCP::LineState lines)
{
    switch (lines)
    {
    case QCP::E_NULL:
        d_ptr->m_bIsVisible = QCP::E_NULL;
        break;
    case QCP::E_Horizontal:
        d_ptr->m_bIsVisible = QCP::E_Horizontal;
        break;
    case QCP::E_Vertical:
        d_ptr->m_bIsVisible = QCP::E_Vertical;
        break;
    case QCP::E_ALL:
        d_ptr->m_bIsVisible = QCP::E_ALL;
        break;
    }

    if (QCPLayer * layer = mParentPlot->layer(LayerName()))
    {
        layer->replot();
    }

    if (d_ptr->m_bIsVisible == QCP::E_NULL)
    {
        for (CrossLinePlot * crossline : CrossLinePlot::m_BrotherLine)
        {
            if (crossline != this)
            {
                crossline->SyncLinePosition(QPoint(), d_ptr->m_dAxisXValue);
            }
        }
    }
}

这篇关于QCustomplot 层 (七)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/975713

相关文章

Qt6中使用qcustomplot时报错:file too big

错误描述:在qt6中使用qcustomplot时报错提示:file too big 提示是.cpp文件太大导致的,需要在.pro文件中再增加一行 QMAKE_CXXFLAGS += "-Wa,-mbig-obj"修改编译器的设置

Qt QCustomPlot画色阶图

工作中用到QCustomPlot画曲线图和色阶图,并且在色阶图上添加文字,圆圈或者几条线段画一些图形,这里写个简单的例子把这几个功能记录一下,代码在这里:  https://download.csdn.net/download/Sakuya__/89681279https://download.csdn.net/download/Sakuya__/89681279

qt的QCustomPlot绘制实时曲线图总结

一、组件的下载 下载下来后文件如下图所示,具有丰富的例程,这个很好,注意后面要用到的c++文件和头文件,听说还有丰富的帮助文档,暂时没有时间去找,大概翻看了一下没有看到 二、拷贝.h 和c++文件到工程目录,如下图;并添加到工程目录中 三、在ui窗口中增加一个QCustomPlot绘图对象,可以用对象提升的办法 四、修改主窗口的头文件,主要增加了起始时间,一个定时器和一个绘图的槽函

【QT】qcustomplot的清除图层里表数据的方法,及错误分析

题记:ui.qcp->graph(0)->data().data()->clear();有用 ui.qcp->graph(0)->data()->clear();,无用,且软件不会报错! 更详细地讨论 QCustomPlot 中的数据清除方法。 QCPGraph::data() 返回一个 QSharedPointer<QCPGraphDataContainer>,该容器提供了对图表数据的访问。

QCustomPlot使用手册目录

QCustomPlot之开始(一) QCustomPlot之个性化外观(二) QCustomPlot之柱状图(三) QCustomPlot之层和布局(四) QCustomPlot之轴矩形和轴(五) QCustomPlot之简单动态图(六) QCustomPlot之参数曲线(七) QCustomPlot之平滑曲线上(八) QCustomPlot之平滑曲线下(九) QCustomPlot之Item(十

【QT教程】使用qcustomplot完成对图像的拖动、框选缩放、自动缩放、游标等操作

目录 1.Qt 配置qcustomplot2.图像拖拽功能3.图像框选放大4.曲线自动缩放5.图像游标6.【完整代码】将曲线抽象成一个类,以便复用 1.Qt 配置qcustomplot 首先下载qcustomplot官网(qcustomplot下载地址)下载最近的源码,我用的是2.1.1版本。下载完成后解压,得到如下文件。 将.h和.cpp文件加入到工程中 如果使用的是Qt

在Qml中使用QCustomPlot

QmlQCustomPlot 基于 QCustomPlot,一个支持在 Qml 中使用的简单包 目录 🔔工程下载🔔快速开始使用cmake构建使用qmake构建 🔔讨论🔔UML 🔔工程下载 GitHub源码下载:https://github.com/MrHulu/QmlQCustomPlot CSDN资源下载 (免费):https://do

QCustomPlot 2.0.1 源码分析

z 目录 The Layering systemQCustomPlot构成QCPLayerQCPGraphQCPAxis 绘制流程交互方式模式流程 矩形选择模式模式流程 成员变量mLayersmGraphsmCurrentLayermPlottablesxAxis, yAxis, xAxis2, yAxis2mInteractions 交互方式mSelectionRectMode 矩形选择模

QCustomplot---动态图

QCustomplot绘制动态曲线图-游标及鼠标跟踪显示数值_qcustomplot 游标-CSDN博客 m_timer = new QTimer(this);connect(m_timer,SIGNAL(timeout()),this,SLOT(slotTimeout()));m_timer->start(50); void MainWindow::slotTimeout()

QCustomplot 坐标轴和网格线(六)

一、概述     前边已经写了5篇对QCustomPlot的讲解,看过上述的几篇文章后,基本就能做一些简单的使用了,但是如果想要做到高度的控制图表,那么坐标轴将是很重要的一部分,因为坐标轴就是图表的一个参考系,没有了参考系那么一切都是天方夜谭。关于QCustomPlot的坐标轴我还是会按照之前的套路,首先对比1.3.2版本和2.0.0beta版本,然后在深入的去分析坐标轴使用。 二、历史版本对