QCustomPlot绘图类详解(大白话)

本文假定你会使用Qt开发,但未接触过QCustomPlot绘图类或者是刚接触。

如何往Qt中引入QCustomPlot

  1. 首先,去官网下载最新版本的源码,注意是QCustomPlot.tar.gz这个文件,里面包含源码和示例。实际上,我们只需要qcustomplot.hqcustomplot.h这两个源文件。
    QCustomPlot绘图类详解(大白话)_第1张图片
  2. 将代码文件拷贝到本地工程,并引入。
    QCustomPlot绘图类详解(大白话)_第2张图片
    QCustomPlot需要依赖printsupport模块,如果你是使用QT+VS开发,配置如下:
    QCustomPlot绘图类详解(大白话)_第3张图片
    如果是Qt Create开发,在.pro文件中添加:QT += QWidget printsupport
  3. 在Qt中新建ui文件,拖拽一个QWidget控件,将其提升为QCustomPlot
    QCustomPlot绘图类详解(大白话)_第4张图片

QCustomPlot常用函数

// 设置背景色
ui.plotWidget->setBackground(QBrush(QColor("#404040")));

// 设置X/Y轴的标签
ui.plotWidget->xAxis->setLabel(QStringLiteral("次数"));

// 设置X/Y轴标签字体
ui.plotWidget->xAxis->setLabelFont(plotFont);

// 设置X/Y轴标签颜色
ui.plotWidget->xAxis->setLabelColor(QColor(Qt::red));

// 设置x=0或y=0所在直线的画笔
ui.plotWidget->xAxis->grid()->setZeroLinePen(QPen(QColor(Qt::yellow)));

// 设置X/Y轴刻度范围
ui.plotWidget->xAxis->setRange(1, PT_CNT);

// 设置X/Y轴刻度数,也就是分为几段
ui.plotWidget->xAxis->ticker()->setTickCount(8);

// 设置X/Y轴刻度值文本的颜色
ui.plotWidget->xAxis->setTickLabelColor(QColor(Qt::green));

// 设置X/Y轴轴线的画笔
ui.plotWidget->xAxis->setBasePen(QPen(QColor(Qt::white), 2, Qt::SolidLine));

// 设置X/Y轴大刻度的画笔,被分段的位置
ui.plotWidget->xAxis->setTickPen(QPen(QColor("#ff00ff")));

// 设置X/Y轴小刻度的画笔
ui.plotWidget->xAxis->setSubTickPen(QPen(QColor("#00ffff")));

// 设置内部网格线的画笔
ui.plotWidget->xAxis->grid()->setPen(QPen(QColor(Qt::darkRed), 1, Qt::DotLine));

// 添加一个图层
ui.plotWidget->addGraph();

// 为对应图层添加数据
ui.plotWidget->graph(0)->addData(keys, values);

// 为图层设置画笔
ui.plotWidget->graph(0)->setPen(QColor(Qt::blue));

// 设置是/否抗锯齿
ui.plotWidget->graph(0)->setAntialiasedFill(true);

// 刷新绘图,更改数据后需手动刷新(缩放会自动刷新)
ui.plotWidget->replot();

// 支持拖拽和缩放
ui.plotWidget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);

绘制直方图

更改QCustomPlot相关属性,这里以颜色修改为主(稍有点乱哈),创建距离-测距次数的直方图。
QCustomPlot绘图类详解(大白话)_第5张图片
相关代码如下:

void PlotTest::InitForm()
{
    ui.plotWidget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);

    ui.plotWidget->setBackground(QBrush(QColor("#404040")));
    ui.plotWidget->xAxis->setLabel(QStringLiteral("次数"));
    ui.plotWidget->yAxis->setLabel(QStringLiteral("距离(cm)"));

    QFont plotFont = font();
    plotFont.setPointSizeF(10.0);

    ui.plotWidget->xAxis->setLabelFont(plotFont);
    ui.plotWidget->yAxis->setLabelFont(plotFont);
    ui.plotWidget->xAxis->setLabelColor(QColor(Qt::red));
    ui.plotWidget->yAxis->setLabelColor(QColor(Qt::red));
    ui.plotWidget->xAxis->grid()->setZeroLinePen(QPen(QColor(Qt::yellow)));
    ui.plotWidget->yAxis->grid()->setZeroLinePen(QPen(QColor(Qt::yellow)));
    ui.plotWidget->xAxis->setRange(1, PT_CNT);
    ui.plotWidget->yAxis->setRange(-10, 90);
    ui.plotWidget->xAxis->ticker()->setTickCount(8);
    ui.plotWidget->yAxis->ticker()->setTickCount(8);
    ui.plotWidget->xAxis->setTickLabelColor(QColor(Qt::green));
    ui.plotWidget->yAxis->setTickLabelColor(QColor(Qt::green));
    ui.plotWidget->xAxis->setBasePen(QPen(QColor(Qt::white), 2, Qt::SolidLine));
    ui.plotWidget->yAxis->setBasePen(QPen(QColor(Qt::white), 2, Qt::SolidLine));
    ui.plotWidget->xAxis->setTickPen(QPen(QColor("#ff00ff")));
    ui.plotWidget->yAxis->setTickPen(QPen(QColor("#ff00ff")));
    ui.plotWidget->xAxis->setSubTickPen(QPen(QColor("#00ffff")));
    ui.plotWidget->yAxis->setSubTickPen(QPen(QColor("#00ffff")));
    ui.plotWidget->xAxis->grid()->setPen(QPen(QColor(Qt::darkRed), 1, Qt::DotLine));
    ui.plotWidget->yAxis->grid()->setPen(QPen(QColor(Qt::darkGreen), 1, Qt::DotLine));

    QVector keys, values;
    for (int i = 1; i <= PT_CNT; i++)
    {
        keys.push_back(i);
        values.push_back(rand() % 100 - 10);
    }
    ui.plotWidget->addGraph();
    ui.plotWidget->graph(0)->addData(keys, values);
    ui.plotWidget->graph(0)->setPen(QColor(Qt::blue));
    ui.plotWidget->graph(0)->setAntialiasedFill(true);
    ui.plotWidget->replot();
}

刷新直方图

刷新直方图比较简单,刷新指定图层的数据即可。有2种方式:

  • 更换数据
ui.plotWidget->graph(0)->data()->clear(); // 清楚图层对应的数据
ui.plotWidget->graph(0)->addData(keys, values); // 添加新的数据
  • 更换图层
ui.plotWidget->clearGraphs(); // 删除图层(单个或所有)
ui.plotWidget->addGraph(); // 新建图层
ui.plotWidget->graph(0)->addData(keys, values); // 添加新数据

注:两种方式会适用于不同的场景下。
QCustomPlot绘图类详解(大白话)_第6张图片

绘制连续的直方图

连续直方图可以理解为:不断往图层里添加数据。需要注意的是,每次添加数据都需要更新刻度范围。代码如下:

void PlotTest::DrawContinueGraph()
{
    QVector keys, values;

    for (int i = 1; i <= PT_CNT; i++)
    {
        keys.push_back(mRefreshCnt * PT_CNT + i);
        values.push_back(rand() % 100 + 1);
    }

    ui.plotWidget->graph(0)->addData(keys, values);
    ui.plotWidget->xAxis->setRange(1, PT_CNT * (mRefreshCnt + 1));
    ui.plotWidget->graph(0)->setAntialiasedFill(true);
    ui.plotWidget->replot();

    mRefreshCnt++;
}

完整代码

// PlotTest.h文件
#pragma once

#include 
#include "ui_PlotTest.h"

class PlotTest : public QWidget
{
    Q_OBJECT

public:
    PlotTest(QWidget *parent = nullptr);
    ~PlotTest();

public:
    void InitForm();            // 初始化控件
    void DrawStaticGraph();     // 绘制静态库
    void DrawDynamicGraph();    // 绘制动态库(单图刷新)
    void DrawContinueGraph();   // 绘制连续图(多图刷新)
    
public slots:
    void on_btnDynamicDraw_clicked();
    void on_btnContinueDraw_clicked();

private:
    Ui::PlotTestClass ui;
    int mRefreshCnt; // 连续刷新次数
};
// PlotTest.cpp文件
#include "PlotTest.h"
#include "CustomPlot\qcustomplot.h"

#define PT_CNT       200    // 点数
#define GRAPH_CNT    5      // 图数

PlotTest::PlotTest(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);

    InitForm();
    mRefreshCnt = 1;
}

PlotTest::~PlotTest()
{

}

void PlotTest::on_btnDynamicDraw_clicked()
{
    ui.btnDynamicDraw->setEnabled(false);
    ui.btnContinueDraw->setEnabled(false);
    mRefreshCnt = 1;

    for (int i = 0; i < 10; i++)
    {
        DrawDynamicGraph();
        Sleep(500);
    }

    ui.btnDynamicDraw->setEnabled(true);
    ui.btnContinueDraw->setEnabled(true);
}

void PlotTest::on_btnContinueDraw_clicked()
{
    ui.btnDynamicDraw->setEnabled(false);
    ui.btnContinueDraw->setEnabled(false);
    mRefreshCnt = 0;
    ui.plotWidget->graph(0)->data()->clear();
    ui.plotWidget->xAxis->setRange(1, PT_CNT);

    for (int i = 0; i < 10; i++)
    {
        DrawContinueGraph();
        Sleep(500);
    }

    ui.btnDynamicDraw->setEnabled(true);
    ui.btnContinueDraw->setEnabled(true);
}

void PlotTest::InitForm()
{
    ui.plotWidget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);

#if 0
    ui.plotWidget->setBackground(QBrush(QColor("#404040")));
    ui.plotWidget->xAxis->setLabel(QStringLiteral("次数"));
    ui.plotWidget->yAxis->setLabel(QStringLiteral("距离(cm)"));

    QFont plotFont = font();
    plotFont.setPointSizeF(10.0);

    ui.plotWidget->xAxis->setLabelFont(plotFont);
    ui.plotWidget->yAxis->setLabelFont(plotFont);
    ui.plotWidget->xAxis->setLabelColor(QColor(Qt::red));
    ui.plotWidget->yAxis->setLabelColor(QColor(Qt::red));
    ui.plotWidget->xAxis->grid()->setZeroLinePen(QPen(QColor(Qt::yellow)));
    ui.plotWidget->yAxis->grid()->setZeroLinePen(QPen(QColor(Qt::yellow)));
    ui.plotWidget->xAxis->setRange(1, PT_CNT);
    ui.plotWidget->yAxis->setRange(-10, 90);
    ui.plotWidget->xAxis->ticker()->setTickCount(8);
    ui.plotWidget->yAxis->ticker()->setTickCount(8);
    ui.plotWidget->xAxis->setTickLabelColor(QColor(Qt::green));
    ui.plotWidget->yAxis->setTickLabelColor(QColor(Qt::green));
    ui.plotWidget->xAxis->setBasePen(QPen(QColor(Qt::white), 2, Qt::SolidLine));
    ui.plotWidget->yAxis->setBasePen(QPen(QColor(Qt::white), 2, Qt::SolidLine));
    ui.plotWidget->xAxis->setTickPen(QPen(QColor("#ff00ff")));
    ui.plotWidget->yAxis->setTickPen(QPen(QColor("#ff00ff")));
    ui.plotWidget->xAxis->setSubTickPen(QPen(QColor("#00ffff")));
    ui.plotWidget->yAxis->setSubTickPen(QPen(QColor("#00ffff")));
    ui.plotWidget->xAxis->grid()->setPen(QPen(QColor(Qt::darkRed), 1, Qt::DotLine));
    ui.plotWidget->yAxis->grid()->setPen(QPen(QColor(Qt::darkGreen), 1, Qt::DotLine));

    QVector keys, values;
    for (int i = 1; i <= PT_CNT; i++)
    {
        keys.push_back(i);
        values.push_back(rand() % 100 - 10);
    }
    ui.plotWidget->addGraph();
    ui.plotWidget->graph(0)->addData(keys, values);
    ui.plotWidget->graph(0)->setPen(QColor(Qt::blue));
    ui.plotWidget->graph(0)->setAntialiasedFill(true);
    ui.plotWidget->replot();
#else
    ui.plotWidget->xAxis->setLabel(QStringLiteral("次数"));
    ui.plotWidget->yAxis->setLabel(QStringLiteral("距离(cm)"));
    ui.plotWidget->xAxis->setRange(1, PT_CNT);
    ui.plotWidget->yAxis->setRange(1, 100);
    ui.plotWidget->xAxis->ticker()->setTickCount(8);
    ui.plotWidget->yAxis->ticker()->setTickCount(8);

    DrawStaticGraph();

#endif
}

void PlotTest::DrawStaticGraph()
{
    QVector keys, values;
    for (int i = 1; i <= PT_CNT; i++)
    {
        keys.push_back(i);
        values.push_back(rand() % 100 + 1);
    }

    ui.plotWidget->addGraph();
    ui.plotWidget->graph(0)->addData(keys, values);
    ui.plotWidget->graph(0)->setPen(QColor(Qt::blue));
    ui.plotWidget->graph(0)->setAntialiasedFill(true);
    ui.plotWidget->replot();
}

void PlotTest::DrawDynamicGraph()
{
    ui.plotWidget->clearGraphs();
    QVector keys, values;
    for (int i = 1; i <= PT_CNT; i++)
    {
        keys.push_back(i);
        values.push_back(rand() % 100 + 1);
    }

    ui.plotWidget->addGraph();
    ui.plotWidget->graph(0)->addData(keys, values);
    ui.plotWidget->xAxis->setRange(1, PT_CNT);
    ui.plotWidget->graph(0)->setAntialiasedFill(true);
    ui.plotWidget->replot();
}

void PlotTest::DrawContinueGraph()
{
    QVector keys, values;

    for (int i = 1; i <= PT_CNT; i++)
    {
        keys.push_back(mRefreshCnt * PT_CNT + i);
        values.push_back(rand() % 100 + 1);
    }

    ui.plotWidget->graph(0)->addData(keys, values);
    ui.plotWidget->xAxis->setRange(1, PT_CNT * (mRefreshCnt + 1));
    ui.plotWidget->graph(0)->setAntialiasedFill(true);
    ui.plotWidget->replot();

    mRefreshCnt++;
}

你可能感兴趣的:(Qt学习笔记,qt,QCustomPlot,大白话)