QCustomPlot安装及demo
QCustomPlot 是一个用于在 Qt 应用程序中创建 2D 绘图和图形的 C++ 类库,它为开发者提供了丰富且便捷的绘图功能.本文主要介绍了QCustomplot的安装及基本使用方法.(版本 Qt 5.14.1及QCustomPlot: Version 2.1.1)
1.运行结果
运行结果如图 ,下图的多通道分析图是便是利用QCustomplot提升形成.整个demo模拟画出了三个不同颜色的曲线,同时设计了滚轮放大缩小以及十字坐标显示以及右键截图等功能.
2.QCustomPlot下载安装
在官网上下载所需要版本的QCustomPlot的压缩包QCustomPlot.tar.gz
官网地址:https://www.qcustomplot.com
下载后进行解压,得到h文件和c文件
3.添加到项目
a.新建qt项目,按照平时的习惯构建即可
b.将qcustomplt的头文件和源文件复制到目录下进行添加,下图为添加成功
c.添加变量,如果你的QT版本是5.0及以上,我所使用的Qt为5.14.2,那么.pro文件中的QT变量必须添加一个printsupport,添加完成之后,保存一下,如图所示
d.操作得到QCustomPlot控件(注:QCustomPlot是继承自 QWidget 的,使用时,首先生成一个QWidget控件,然后右键点击这个控件,选择提升为QCustomPlot,这样我们就得到了一个可操作的 QCustomPlot 控件)
4.项目运行
至此,安装和配置QCustomplot步骤全部完成.
5.demo源码
注释详细
mianwindow.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "qcustomplot.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
private:
Ui::MainWindow *ui;
// 十字线成员变量
QCPItemStraightLine *crosshairH; // 水平十字线
QCPItemStraightLine *crosshairV; // 垂直十字线
QCPItemText *coordText; // 坐标显示文本
// 初始化函数
void setupCustomPlot(); // 初始化图表
void setupInteractions(); // 初始化交互功能
// 右键菜单函数
void showContextMenu(const QPoint &pos);
};
#endif // MAINWINDOW_H
mianwindow.c文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//初始化图表
setupCustomPlot();
//初始化交互功能
setupInteractions();
}
MainWindow::~MainWindow()
{
delete ui;
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->widget && event->type() == QEvent::Wheel)
{
QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
if (QApplication::keyboardModifiers() & Qt::ControlModifier)
{
double factor = wheelEvent->angleDelta().y() > 0 ? 0.85 : 1.15; // 缩放因子
ui->widget->xAxis->scaleRange(factor, ui->widget->xAxis->range().center());
ui->widget->yAxis->scaleRange(factor, ui->widget->yAxis->range().center());
ui->widget->replot();
return true;
}
}
return QMainWindow::eventFilter(obj, event);
}
void MainWindow::setupCustomPlot()
{
QCustomPlot *customPlot = ui->widget;
// ============ 1. 图表基本设置 ============
// 设置背景色
customPlot->setBackground(QBrush(QColor(245, 245, 245)));
// 添加标题
customPlot->plotLayout()->insertRow(0);
QCPTextElement *title = new QCPTextElement(customPlot, "多通道信号分析", QFont("微软雅黑", 12, QFont::Bold));
customPlot->plotLayout()->addElement(0, 0, title);
// ============ 2. 创建多条曲线 ============
customPlot->addGraph(); // 通道1
customPlot->addGraph(); // 通道2
customPlot->addGraph(); // 通道3
// ============ 3. 设置曲线样式 ============
// 通道1:红色实线,带圆形数据点
customPlot->graph(0)->setPen(QPen(QColor(255, 50, 50), 1.5));
customPlot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 5));
customPlot->graph(0)->setName("ECG信号");
// 通道2:绿色虚线,带方形数据点
QPen greenPen(QColor(50, 180, 50), 1.5);
greenPen.setStyle(Qt::DashLine);
customPlot->graph(1)->setPen(greenPen);
customPlot->graph(1)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssSquare, 5));
customPlot->graph(1)->setName("EMG信号");
// 通道3:蓝色点线,带菱形数据点
QPen bluePen(QColor(50, 50, 255), 1.5);
bluePen.setStyle(Qt::DotLine);
customPlot->graph(2)->setPen(bluePen);
customPlot->graph(2)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDiamond, 5));
customPlot->graph(2)->setName("EEG信号");
// ============ 4. 生成模拟生物信号数据 ============
QVector<double> x(500), y0(500), y1(500), y2(500);
for (int i = 0; i < 500; ++i)
{
x[i] = i * 0.1; // 20ms采样间隔
// ECG信号 (模拟心电)
y0[i] = 1.5 * qSin(i * 0.1) + 0.3 * qSin(i * 0.5) + (qrand() % 100) * 0.01;
// EMG信号 (模拟肌电)
y1[i] = 0.8 * qCos(i * 0.15) + (qrand() % 100) * 0.05 - 2;
// EEG信号 (模拟脑电)
y2[i] = 0.5 * qSin(i * 0.05) + 0.2 * qCos(i * 0.3) + (qrand() % 100) * 0.02 + 2;
}
// 设置数据
customPlot->graph(0)->setData(x, y0);
customPlot->graph(1)->setData(x, y1);
customPlot->graph(2)->setData(x, y2);
// ============ 5. 坐标轴设置 ============
// X轴
customPlot->xAxis->setLabel("时间 (s)");
customPlot->xAxis->setRange(0, 10); // 10秒数据
customPlot->xAxis->grid()->setSubGridVisible(true);
// Y轴
customPlot->yAxis->setLabel("幅值 (mV)");
customPlot->yAxis->setRange(-5, 5);
customPlot->yAxis->grid()->setSubGridVisible(true);
// 网格样式
customPlot->xAxis->grid()->setPen(QPen(QColor(200, 200, 200), 1, Qt::DotLine));
customPlot->yAxis->grid()->setPen(QPen(QColor(200, 200, 200), 1, Qt::DotLine));
customPlot->xAxis->grid()->setSubGridPen(QPen(QColor(220, 220, 220), 1, Qt::DotLine));
customPlot->yAxis->grid()->setSubGridPen(QPen(QColor(220, 220, 220), 1, Qt::DotLine));
// ============ 6. 图例设置 ============
customPlot->legend->setVisible(true);
customPlot->legend->setFont(QFont("Arial", 9));
customPlot->legend->setBrush(QBrush(QColor(255, 255, 255, 200))); // 半透明背景
customPlot->legend->setBorderPen(QPen(QColor(180, 180, 180), 1));
// 图例位置
customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignTop|Qt::AlignRight);
// ============ 7. 十字线初始化 ============
// 水平线
crosshairH = new QCPItemStraightLine(customPlot);
crosshairH->setPen(QPen(QColor(150, 150, 150), 1, Qt::DashLine));
crosshairH->setVisible(false);
// 垂直线
crosshairV = new QCPItemStraightLine(customPlot);
crosshairV->setPen(QPen(QColor(150, 150, 150), 1, Qt::DashLine));
crosshairV->setVisible(false);
// 坐标标签
coordText = new QCPItemText(customPlot);
coordText->setPositionAlignment(Qt::AlignLeft|Qt::AlignTop);
coordText->position->setType(QCPItemPosition::ptAxisRectRatio);
coordText->position->setCoords(0.02, 0.02); // 左上角
coordText->setText("X: -, Y: -");
coordText->setTextAlignment(Qt::AlignLeft);
coordText->setFont(QFont(font().family(), 9));
coordText->setPadding(QMargins(5, 5, 5, 5));
coordText->setBrush(QBrush(QColor(255, 255, 255, 200)));
coordText->setPen(QPen(QColor(100, 100, 100)));
// ============ 8. 重绘图表 ============
customPlot->replot();
}
void MainWindow::setupInteractions()
{
QCustomPlot *customPlot = ui->widget;
// 启用鼠标拖拽和缩放
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
// 鼠标移动事件 - 显示十字线和坐标
connect(customPlot, &QCustomPlot::mouseMove, this, [=](QMouseEvent *event)
{
double x = customPlot->xAxis->pixelToCoord(event->pos().x());
double y = customPlot->yAxis->pixelToCoord(event->pos().y());
// 更新坐标显示
coordText->setText(QString("X: %1 s\nY: %2 mV").arg(x, 0, 'f', 2).arg(y, 0, 'f', 2));
// 显示十字线
crosshairV->point1->setCoords(x, customPlot->yAxis->range().lower);
crosshairV->point2->setCoords(x, customPlot->yAxis->range().upper);
crosshairH->point1->setCoords(customPlot->xAxis->range().lower, y);
crosshairH->point2->setCoords(customPlot->xAxis->range().upper, y);
crosshairV->setVisible(true);
crosshairH->setVisible(true);
customPlot->replot();
});
// 鼠标离开图表区域时隐藏十字线
connect(customPlot, &QCustomPlot::mouseRelease, this, [=]()
{
crosshairV->setVisible(false);
crosshairH->setVisible(false);
customPlot->replot();
});
// 旧版兼容的缩放控制
customPlot->setInteraction(QCP::iRangeZoom, true); // 启用缩放
// 实现Ctrl+滚轮缩放 (手动实现)
customPlot->installEventFilter(this); // 需要添加eventFilter函数
// 双击重置视图
connect(customPlot, &QCustomPlot::mouseDoubleClick, this, [=]()
{
customPlot->rescaleAxes();
customPlot->replot();
});
// 右键菜单
customPlot->setContextMenuPolicy(Qt::CustomContextMenu);
connect(customPlot, &QCustomPlot::customContextMenuRequested, this, &MainWindow::showContextMenu);
}
void MainWindow::showContextMenu(const QPoint &pos)
{
QCustomPlot *customPlot = ui->widget;
QMenu *menu = new QMenu(this);
menu->setAttribute(Qt::WA_DeleteOnClose);
// 添加菜单项
menu->addAction("保存图像", this, [=]()
{
QString fileName = QFileDialog::getSaveFileName(this, "保存图像", "", "PNG (*.png);;JPG (*.jpg);;PDF (*.pdf)");
if (!fileName.isEmpty())
{
if (fileName.endsWith(".png"))
customPlot->savePng(fileName);
else if (fileName.endsWith(".jpg"))
customPlot->saveJpg(fileName);
else if (fileName.endsWith(".pdf"))
customPlot->savePdf(fileName);
}
});
menu->addSeparator();
menu->addAction("重置视图", this, [=]()
{
customPlot->rescaleAxes();
customPlot->replot();
});
menu->addAction("显示/隐藏图例", this, [=]()
{
customPlot->legend->setVisible(!customPlot->legend->visible());
customPlot->replot();
});
menu->popup(customPlot->mapToGlobal(pos));
}
希望对大家,有所帮助.后续会进行频谱,眼图,瀑布图等的绘画