Qt——示波器/图表 QCustomPlot

一、介绍

    QCustomPlot是一个用于绘图和数据可视化的Qt C++小部件。它没有进一步的依赖关系,提供友好的文档帮助。这个绘图库专注于制作好看的,出版质量的2D绘图,图形和图表,以及为实时可视化应用程序提供高性能。
    QCustomPlot可以导出各种格式,如矢量化的PDF文件和光栅化的图像,如PNG, JPG和BMP。QCustomPlot是用于在应用程序中显示实时数据以及为其他媒体生成高质量图的解决方案。

在这里插入图片描述

二、配置

1)下载
官方网站
http://www.qcustomplot.com/

    从官网下载文件,选择2.1版本以上,因为这会开始支持Qt6了。可以选择源文件+实例+说明文档全部下载,或者选择下载单动态库或纯源码,文件不大建议全部下载。

在这里插入图片描述

2)QtCreator配置
新建一个Qt Widgets Application工程。

在这里插入图片描述

     把下载好的qcustomplot.h和qcustomplot.cpp放到工程下,右击项目,添加现有文件。

在这里插入图片描述

    对话框中选择选择qcustomplot.h和qcustomplot.cpp文件添加到项目中,并在pro文件中添加Qt += printsupport。

在这里插入图片描述

    双击mainwindows.ui进入Designer界面,新建一个widget部件。

在这里插入图片描述

     右击widget部件,选择提升为...。

在这里插入图片描述

     在类名称里面输入QCustomPlot,选择“添加”,然后选择“提升”。

    这里要注意头文件路径,如果你是放在最外层(和pro文件同级),直接默认值就行。如果是放在某文件夹下,比如新建了一个custom文件夹并放置在里面,那么头文件这一栏应该是“custom/qcustomplot.h”。

在这里插入图片描述

     提升之后,widget类已经被改成QCustomPlot。

在这里插入图片描述

     在mianwindows.cpp构造函数添加如下demo代码。        

// add two new graphs and set their look:
ui->widget->addGraph();
ui->widget->graph(0)->setPen(QPen(Qt::blue)); // line color blue for first graph
ui->widget->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); // first graph will be filled with translucent blue
ui->widget->addGraph();
ui->widget->graph(1)->setPen(QPen(Qt::red)); // line color red for second graph
// generate some points of data (y0 for first, y1 for second graph):
QVector x(251), y0(251), y1(251);
for (int i=0; i<251; ++i)
{
x[i] = i;
y0[i] = qExp(-i/150.0)*qCos(i/10.0); // exponentially decaying cosine
y1[i] = qExp(-i/150.0); // exponential envelope
}
// configure right and top axis to show ticks but no labels:
// (see QCPAxisRect::setupFullAxesBox for a quicker method to do this)
ui->widget->xAxis2->setVisible(true);
ui->widget->xAxis2->setTickLabels(false);
ui->widget->yAxis2->setVisible(true);
ui->widget->yAxis2->setTickLabels(false);
// make left and bottom axes always transfer their ranges to right and top axes:
connect(ui->widget->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->widget->xAxis2, SLOT(setRange(QCPRange)));
connect(ui->widget->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->widget->yAxis2, SLOT(setRange(QCPRange)));
// pass data points to graphs:
ui->widget->graph(0)->setData(x, y0);
ui->widget->graph(1)->setData(x, y1);
// let the ranges scale themselves so graph 0 fits perfectly in the visible area:
ui->widget->graph(0)->rescaleAxes();
// same thing for graph 1, but only enlarge ranges (in case graph 1 is smaller than graph 0):
ui->widget->graph(1)->rescaleAxes(true);
// Note: we could have also just called ui->widget->rescaleAxes(); instead
// Allow user to drag axis ranges with mouse, zoom with mouse wheel and select graphs by clicking:
ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);

    编译构建项目成功后,执行即可看到demo图表。

在这里插入图片描述

3)添加说明文档
下载的文档可以直接添加到QtCreator的帮助里面。

在这里插入图片描述

    把文件放到 D:\Qt\Qt5.9.6\Tools\QtCreator\share\doc\qtcreator底下

在这里插入图片描述

     QtCreator选择工具-选项。

在这里插入图片描述

     选择-文档-添加,在弹出的界面选择把qcustomplot.qch文件加进来。

在这里插入图片描述

     如此,我们在帮助界面搜索qcustomplot就可以直接浏览帮助文档。         
    
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b47d85cd4eaa4d8dad4300c796aee8dc.png#pic_center)

三、常用功能详解

1)曲线
使用addGraph()方法新建曲线,返回一个QCPGraph对象指针,后续使用此指针或者根据索引获取指针对曲线动作。

    建议使用保存对象指针方法操作曲线,因为索引容易误操作,比如当新建两条曲线的时候,删除第一条,第二条索引会从1变成0,高亮的时候索引也会有异常。

//初始化返回类指针
QCPGraph *graph1 = ui->plot->addGraph();
//根据索引获取类指针
QCPGraph *graph1 = ui->plot->graph(index)
如果你需要两条曲线在不同的坐标系,比如X轴相同,Y轴不同,那么就需要在初始化的时候指定坐标系,或者后续指定。

QCPGraph *graph1 = ui->plot->addGraph(ui->plot->xAxis,ui->plot->yAxis);
QCPGraph *graph2 = ui->plot->addGraph(ui->plot->xAxis,ui->plot->yAxis2);

//或者在addGraph之后使用
graph1->setKeyAxis(ui->plot->xAxis);
graph1->setValueAxis(ui->plot->yAxis);
graph2->setKeyAxis(ui->plot->xAxis2);
graph2->setValueAxis(ui->plot->yAxis2);
使用setData()方法设置曲线坐标数据,坐标数据使用QVector封装,使用此方法会覆盖原先的曲线。注意这里x和y的动态数组长度要一致,否则控制台会报错并失效。

QVector x0(251), y0(251);
for (int i=0; i<251; ++i)
{
x[i] = i;
y0[i] = qExp(-i/150.0)*qCos(i/10.0);
}
ui->plot->graph(0)->setData(x0,y0);//写入数据
使用addData()方法在原先基础上添加数据,适用于动态曲线,当然如果一直重新setData也是可以,不建议这么做。

ui->plot->graph(0)->addData(x0, y0)
使用clear()清空数据,但是曲线还保留着。

ui->plot->graph(0)->data()->clear();
使用setName()方法设置曲线名称,name方法返回曲线名称。

ui->plot->graph(0)->setName(QString(“graph1”));
qDebug()<Plot->graph(0)->name();
使用removeGraph()方法传入QCPGraph指针或者索引移除曲线。

ui->plot->removeGraph(0);
ui->plot->removeGraph(graph1);
设置曲线画笔颜色、宽度、样式。

ui->plot->graph(0)->setPen(QPen(QColor(120, 120, 120), 2));
设置曲线使用刷子。

ui->plot->graph(1)->setBrush(QColor(200, 200, 200, 20));

在这里插入图片描述

    使用setChannelFillGraph()把通道2包含在1里面,这样刷子颜色就不会透视。

QCPGraph *graph2 = ui->widget->addGraph();
graph2->setData(x2, y2);
graph2->setPen(Qt::NoPen);
graph2->setBrush(QColor(200, 200, 200, 20));
graph2->setChannelFillGraph(graph1);

在这里插入图片描述

     使用setScatterStyle()设置曲线散点的样式。

ui->plot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(Qt::black, 1.5), QBrush(Qt::white), 9));
在这里插入图片描述

2)柱状图
实例化QCPBars()。

QCPBars *bars1 = new QCPBars(ui->widget->xAxis, ui->widget->yAxis);
使用setWidth()设置柱状图宽度

bars1->setWidth(10);
使用setPen()设置画笔

bars1->setPen(QPen(QColor(120, 120, 120), 2));
使用setBrush()设置刷子颜色填充。

bars1->setBrush(QColor(10, 140, 70, 160));
使用moveAbove()设置栏2在1的上方。

bars2->moveAbove(bars1);
在这里插入图片描述

3)坐标轴
在这里插入图片描述

    使用setVisible()方法设置是否显示。

ui->plot->xAxis2->setVisible(true);
ui->plot->yAxis2->setVisible(true);
使用setTickLabels()方法设置是否显示刻度。

ui->widget->xAxis2->setTickLabels(false);
ui->widget->yAxis2->setTickLabels(false);
使用rescaleAxes()方法设置自适应坐标轴,防止因为坐标轴范围过长而出现大量无数据地带

ui->Plot->graph(0)->rescaleAxes();
使用setRange()设置坐标轴范围,使用range()获取坐标轴范围数值。

ui->plot->xAxis->setRange(0, 100);
ui->plot->yAxis->setRange(0, 100);
QCPRange XAxis_Range=ui->plot->xAxis->range();
缩放、自适应等会触发rangeChanged()信号,同步使用setRange(),保证上下、左右坐标一致。

connect(ui->plot->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->plot->xAxis2, SLOT(setRange(QCPRange)));
connect(ui->plot->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->plot->yAxis2, SLOT(setRange(QCPRange)));
3)样式
使用setTickLabelColor()设置坐标轴标签的颜色。

ui->plot->xAxis->setTickLabelColor(Qt::red);
ui->plot->yAxis->setTickLabelColor(Qt::red);
使用setTickPen()设置含标签的刻度的画笔的颜色、线宽和样式。

ui->widget->xAxis->setTickPen(QPen(Qt::red, 1));
ui->widget->yAxis->setTickPen(QPen(Qt::red, 1));
使用setSubTickPen()设置不含标签的刻度的画笔的颜色、线宽和样式。

ui->widget->xAxis->setSubTickPen(QPen(Qt::red, 1));
ui->widget->yAxis->setSubTickPen(QPen(Qt::red, 1));
使用setBasePen()设置坐标轴画笔的颜色、线宽和样式。

ui->plot->xAxis->setBasePen(QPen(Qt::red, 1));
ui->plot->yAxis->setBasePen(QPen(Qt::red, 1));
使用setSubGridVisible()设置是否显示二级网格。

ui->plot->xAxis->grid()->setSubGridVisible(true);
ui->plot->yAxis->grid()->setSubGridVisible(true);
在这里插入图片描述

    使用setPen()设置网格的画笔的颜色、线宽和样式。

ui->plot->xAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
ui->plot->yAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
使用setSubGridPen()设置二级网格的画笔的颜色、线宽和样式。

ui->plot->xAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
ui->plot->yAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
使用setZeroLinePen()设置零线的画笔的颜色、线宽和样式。

ui->plot->xAxis->grid()->setZeroLinePen(Qt::NoPen);
ui->plot->yAxis->grid()->setZeroLinePen(Qt::NoPen);
使用setBackground()设置背景颜色,设置渐变色,也可以直接使用图片,纯色刷子来当背景。

QLinearGradient plotGradient;
plotGradient.setStart(0, 0);
plotGradient.setFinalStop(0, 350);
plotGradient.setColorAt(0, QColor(80, 80, 80));
plotGradient.setColorAt(1, QColor(50, 50, 50));
ui->plot->setBackground(plotGradient);

QLinearGradient axisRectGradient;
axisRectGradient.setStart(0, 0);
axisRectGradient.setFinalStop(0, 350);
axisRectGradient.setColorAt(0, QColor(80, 80, 80));
axisRectGradient.setColorAt(1, QColor(30, 30, 30));
ui->widget->axisRect()->setBackground(axisRectGradient);
使用setUpperEnding()设置上轴结束的样式。

ui->plot->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
ui->plot->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);

在这里插入图片描述

4)图例

在这里插入图片描述

    使用setVisible()设置图例是否显示。

ui->plot->legend->setVisible(true);
使用setFillOrder()设置图例信息的水平方向。

ui->plot->legend->setFillOrder(QCPLayoutGrid::foColumnsFirst);

在这里插入图片描述

     使用addElement()设置图例显示的坐标、位置和比例。

ui->plot->plotLayout()->addElement(1 , 0, ui->plot->legend);
在这里插入图片描述

    使用setBorderPen()设置图例边框颜色、线宽、样式。

ui->plot->legend->setBorderPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
使用setRowStretchFactor()设置显示比例,图例所在框的大小。

ui->plot->plotLayout()->setRowStretchFactor(1, 0.001);
5)其他
使用setInteractions()方法设置交互策略

ui->Plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
//放大拖拽选中等枚举
enum Interaction { iRangeDrag = 0x001 //左键点击可拖动
,iRangeZoom = 0x002 //范围可通过鼠标滚轮缩放
,iMultiSelect = 0x004 //可选中多条曲线
,iSelectPlottables = 0x008 //线条可选中
,iSelectAxes = 0x010 //坐标轴可选
,iSelectLegend = 0x020 //图例是可选择的
,iSelectItems = 0x040 //可选择项(矩形、箭头、文本项等
,iSelectOther = 0x080 //所有其他对象都是可选的
};
使用replot()重新启动绘制,当你需要一条动态曲线的时候,除了动态的addData(),还需要不断的使用replot()进行后续的绘制。

ui->plot->replot();
保存成Pdf、Png、Jpg、Bmp格式文件。

bool savePdf (const QString &fileName, int width=0, int height=0, QCP::ExportPen exportPen=QCP::epAllowCosmetic, const QString &pdfCreator=QString(), const QString &pdfTitle=QString())

bool savePng (const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)

bool saveJpg (const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)

bool saveBmp (const QString &fileName, int width=0, int height=0, double scale=1.0, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)

在这里插入图片描述

     图例与曲线选中状态绑定。

//响应图例被选中信号
connect(ui->channelChart,&QCustomPlot::legendClick,
this,[=](QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event){
m_grap_A->setSelection(ui->channelChart->legend->item(0)->selected()?
QCPDataSelection(m_grap_A->data().data()->dataRange()):
QCPDataSelection());

}

//响应曲线被选中信号
connect(ui->channelChart,&QCustomPlot::plottableClick,
this,[=](QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event){
ui->channelChart->legend->item(0)->setSelected(m_grap_A->selected());
}

在这里插入图片描述

    QPen样式

在这里插入图片描述

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 对于串口Qt示波器的源代码,以下是一个简单的示例: 首先,需要引入Qt的串口和图形库头文件: ``` #include <QSerialPort> #include <QSerialPortInfo> #include <QtCharts/QChartView> #include <QtCharts/QLineSeries> ``` 接下来,可以创建一个Qt窗口类,继承自QWidget,并将其设置为主窗口: ``` class MainWindow : public QWidget { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); private: QSerialPort *serialPort; QtCharts::QChartView *chartView; QtCharts::QLineSeries *series; private slots: void readData(); }; ``` 在构造函数中进行初始化设置,包括串口的初始化和示波器图形的初始化。 ``` MainWindow::MainWindow(QWidget *parent) : QWidget(parent) { // 初始化串口 serialPort = new QSerialPort(this); serialPort->setPortName("COM1"); serialPort->setBaudRate(QSerialPort::Baud9600); serialPort->setDataBits(QSerialPort::Data8); serialPort->setParity(QSerialPort::NoParity); serialPort->setStopBits(QSerialPort::OneStop); serialPort->setFlowControl(QSerialPort::NoFlowControl); serialPort->open(QIODevice::ReadOnly); // 初始化示波器图形 chartView = new QtCharts::QChartView(this); chartView->setRenderHint(QPainter::Antialiasing); series = new QtCharts::QLineSeries(); chartView->chart()->addSeries(series); chartView->chart()->setTitle("Serial Port Oscilloscope"); chartView->chart()->createDefaultAxes(); chartView->chart()->axisX()->setTitleText("Time"); chartView->chart()->axisY()->setTitleText("Voltage"); chartView->chart()->legend()->setVisible(false); // 设置读取串口数据的槽函数 connect(serialPort, SIGNAL(readyRead()), this, SLOT(readData())); } ``` 最后,实现读取串口数据的槽函数,并对数据进行处理和更新图形: ``` void MainWindow::readData() { QByteArray data = serialPort->readAll(); // 根据串口数据进行处理,更新示波器图形 // ... // 示例:假设串口数据为一串实数,表示电压值 foreach (const auto &value, data.split(' ')) { qreal voltage = value.toDouble(); series->append(series->count(), voltage); } } ``` 以上是一个简单的串口Qt示波器的源代码示例,通过这段代码可以实现读取串口数据并在示波器图形上进行实时显示。 ### 回答2: 串口 Qt示波器源代码是一个使用Qt库编写的程序,它可以通过串口与设备进行通信,并且能够显示设备发送的数据以及将发送的数据通过串口发送给设备。 以下是一个简单的串口Qt示波器源代码的示例: ```cpp #include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo> #include <QApplication> #include <QWidget> #include <QVBoxLayout> #include <QLabel> #include <QChartView> #include <QSplineSeries> #include <QValueAxis> #include <QTimer> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 创建串口对象 QSerialPort serial; serial.setPortName("COM1"); // 设置串口名称 serial.setBaudRate(QSerialPort::Baud9600); // 设置波特率 serial.setDataBits(QSerialPort::Data8); // 设置数据位 serial.setParity(QSerialPort::NoParity); // 设置奇偶校验 serial.setStopBits(QSerialPort::OneStop); // 设置停止位 serial.setFlowControl(QSerialPort::NoFlowControl); // 设置流控制 // 创建示波器曲线 QSplineSeries *series = new QSplineSeries(); QChart *chart = new QChart(); chart->addSeries(series); chart->createDefaultAxes(); chart->axisX()->setRange(0, 100); // 设置X轴范围 chart->axisY()->setRange(0, 100); // 设置Y轴范围 // 创建示波器视图 QChartView *chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); // 创建主窗口布局 QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(chartView); // 创建主窗口 QWidget window; window.setLayout(layout); window.show(); // 创建定时器,定时更新示波器数据 QTimer timer; timer.setInterval(100); // 设置定时器间隔 QObject::connect(&timer, &QTimer::timeout, [&]() { // 从串口读取数据 if (serial.isOpen() && serial.isReadable()) { QByteArray data = serial.readAll(); // 处理数据,并显示在示波器上 foreach(char value, data) { int val = static_cast<int>(value); // 将字节转换为整数值 series->append(series->count(), val); // 将数据添加到示波器曲线上 } } }); // 打开串口 if (serial.open(QIODevice::ReadOnly)) { // 启动定时器 timer.start(); // 运行应用程序 return app.exec(); } else { return -1; } } ``` 以上是一个简单的串口Qt示波器源代码示例,该程序可以打开指定的串口,读取串口数据,并将读取的数据显示在示波器曲线上。使用者可以根据需要进行修改和扩展。 ### 回答3: 串口 Qt示波器源代码的实现可以通过以下步骤进行: 1. 首先,在Qt的项目中引入串口库和绘图库,可以使用Qt的串口和绘图模块,也可以使用第三方库,如QSerialPort和QtCharts。 2. 创建一个主窗口,可以使用Qt的MainWindow类来实现,该窗口用于显示示波器的界面和图形。 3. 在主窗口中添加一个串口设置界面,可以包括串口号、波特率和其他设置选项,以便用户可以选择需要连接的串口和相应的参数。 4. 创建一个串口对象,并在串口设置界面中设置相应的参数。使用Qt的QSerialPort类可以轻松地进行串口通信。 5. 在主窗口中添加一个绘图区域,用于绘制示波器的波形。可以使用Qt的绘图类来实现,如QPainter和QPen。 6. 在串口对象中设置数据接收槽函数,当串口接收到数据时,调用槽函数读取并解析数据,然后将数据传递给绘图区域进行绘制。可以使用Qt的信号与槽机制来实现数据的传递和处理。 7. 在主窗口的界面中添加一些控件,如开始按钮、停止按钮和清空按钮,以实现示波器的控制功能。 8. 在开始按钮的点击事件中,打开串口并开始接收数据;在停止按钮的点击事件中,关闭串口和停止接收数据;在清空按钮的点击事件中,清除绘图区域的波形。 9. 最后,运行程序,连接串口,启动示波器,并可以看到串口接收到的数据在绘图区域中实时绘制出来。 以上是一个基本的串口Qt示波器的源代码实现步骤,你可以根据需求和具体情况进行相应的修改和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值