功能预期:
在简单显示曲线()基础上加功能:
1.在曲线区域里,X轴可以随鼠标滚轮变化将图像缩放、随鼠标左键进行曲线移动;
2.在曲线区域里,Y轴的量程可以随Y轴数据大小自适应;
3.可以动态显示最新的数据。
4.拓展:再增加一条曲线同时显示
代码实现
具体细节已在注释中标记清楚
mainwindow.h
cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "qcustomplot.h" // 引入QCustomPlot头文件
#include <QWheelEvent> // 引入QWheelEvent头文件
#include <QMouseEvent> // 引入QMouseEvent头文件
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QCustomPlot *customPlot; // 添加QCustomPlot指针
QTimer *dataTimer; // 定时器
QVector<double> xData, yData; // 数据存储
void updatePlot(); // 更新图表的函数
void wheelEvent(QWheelEvent *event) override; // 确保加上 override
void mousePressEvent(QMouseEvent *event) override; // 鼠标按下事件
void mouseMoveEvent(QMouseEvent *event) override; // 鼠标移动事件
void mouseReleaseEvent(QMouseEvent *event) override; // 鼠标释放事件
bool dragging = false; // 是否正在拖动
QPoint lastMousePos; // 记录鼠标位置
};
#endif // MAINWINDOW_H
main.cpp
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
void MainWindow::updatePlot()
{
// 生成新的数据点
static double time = 0;
static double signalValue = 0;
// 生成新信号值(如正弦波)
signalValue = 65 * qSin(time);
time += 0.1;
// 保存数据
xData.append(time);
yData.append(signalValue);
// 更新图表
customPlot->graph(0)->setData(xData, yData);
// 自动调整Y轴范围
customPlot->yAxis->rescale(true);
// 更新X轴的范围(保持当前显示区间的时间轴范围)
double lowerX = customPlot->xAxis->range().lower;
double upperX = customPlot->xAxis->range().upper;
// 设置X轴范围,确保X轴根据时间区间自动调整
if (time > upperX) {
customPlot->xAxis->setRange(lowerX + 0.1, upperX + 0.1); // 保持动态显示10秒的数据
}
//刷新数据显示
ui->Hvalue_label->setText(QString::number(signalValue));
ui->Svalue_label->setText(QString::number(time));
// 刷新图表
customPlot->replot();
}
void MainWindow::wheelEvent(QWheelEvent *event)
{
// 检查鼠标指针是否在 customPlot 区域内
if (!customPlot->geometry().contains(event->pos())) {
// 如果不在 customPlot 区域内,直接返回
return;
}
// 获取当前X轴范围
double currentRange = customPlot->xAxis->range().upper - customPlot->xAxis->range().lower;
// 获取滚轮的增量
int a = event->angleDelta().y(); // 获取滚动的垂直方向(正为向上滚动,负为向下滚动)
// 设定缩放步长
double zoomFactor = 0.1; // 每次滚动缩放的比例(可调整)
if (a > 0) {
// 向上滚动,缩小X轴范围
customPlot->xAxis->setRange(customPlot->xAxis->range().lower + zoomFactor * currentRange,
customPlot->xAxis->range().upper - zoomFactor * currentRange);
} else {
// 向下滚动,放大X轴范围
customPlot->xAxis->setRange(customPlot->xAxis->range().lower - zoomFactor * currentRange,
customPlot->xAxis->range().upper + zoomFactor * currentRange);
}
// 确保X轴的范围不小于0
if (customPlot->xAxis->range().lower < 0) {
customPlot->xAxis->setRange(0, customPlot->xAxis->range().upper);
}
// 重新绘制图表
customPlot->replot();
}
// 鼠标按下事件
void MainWindow::mousePressEvent(QMouseEvent *event)
{
// 检查鼠标指针是否在 customPlot 区域内
if (!customPlot->geometry().contains(event->pos())) {
// 如果不在 customPlot 区域内,直接返回
return;
}
if (event->button() == Qt::LeftButton) {
// 鼠标左键按下,记录鼠标当前位置
lastMousePos = event->pos();
dragging = true;
}
}
// 鼠标移动事件
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if (dragging) {
// 计算鼠标拖动的距离
int X = event->pos().x() - lastMousePos.x();
// 根据移动的距离调整X轴范围
// double currentRange = customPlot->xAxis->range().upper - customPlot->xAxis->range().lower;
customPlot->xAxis->setRange(customPlot->xAxis->range().lower -X * 0.1, customPlot->xAxis->range().upper -X * 0.1);
// 更新最后的鼠标位置
lastMousePos = event->pos();
// 重新绘制图表
customPlot->replot();
}
}
// 鼠标释放事件
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
dragging = false;
}
}
mainwindow.cpp
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTimer>
#include <QVector>
#include <cmath> // 使用数学函数
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);// 初始化 UI
// ui->Hvalue_label->setText(QString::number(0)); //初始化label的数据
// 初始化QCustomPlot
// 使用UI的customPlot名字而不是创建一个新的。
customPlot = ui->customPlot1;
// customPlot = new QCustomPlot(this);
// setCentralWidget(customPlot);
// 设置 customPlot 以便它接收焦点,确保能够处理事件
customPlot->setFocus();
// 确保QCustomPlot能够接收鼠标事件
customPlot->setFocusPolicy(Qt::StrongFocus); // 设置焦点策略,确保能够接收事件
//避免其他控件(比如按钮、标签等)覆盖在其上面,或者其他控件阻止了事件的传递
customPlot->setAttribute(Qt::WA_TransparentForMouseEvents);
// 配置图表
customPlot->addGraph();
customPlot->graph(0)->setPen(QPen(Qt::red)); // 设置曲线颜色
// customPlot->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); // 曲线与X轴包围区的颜色
//设置XY轴的名字
customPlot->xAxis->setLabel("时间 (s)");
customPlot->yAxis->setLabel("相对地面高度");
// 启用自动缩放 在updatePlot中更新Y轴范围
// customPlot->graph(0)->rescaleAxes(true); //打开注释将开启自适应量程功能
//customPlot->xAxis->setRange(0, 20);
// customPlot->yAxis->setRange(0, 120);
// 初始化定时器
dataTimer = new QTimer(this);
connect(dataTimer, &QTimer::timeout, this, &MainWindow::updatePlot);
dataTimer->start(20); // 每20毫秒更新一次
// 初始化数据
xData.clear();
yData.clear();
}
MainWindow::~MainWindow()
{
delete ui;
}
细节注意:
// 设置 customPlot 以便它接收焦点,确保能够处理事件 customPlot->setFocus(); // 确保QCustomPlot能够接收鼠标事件 customPlot->setFocusPolicy(Qt::StrongFocus); // 设置焦点策略,确保能够接收事件 //避免其他控件(比如按钮、标签等)覆盖在其上面,或者其他控件阻止了事件的传递 customPlot->setAttribute(Qt::WA_TransparentForMouseEvents);
这里主要解决:customPlot1区域里不能实现wheelEvent的函数,在其他界面的区域可以实现wheelEvent函数
// 检查鼠标指针是否在 customPlot 区域内
if (!customPlot->geometry().contains(event->pos())) {
// 如果不在 customPlot 区域内,直接返回
return;
}
这里主要解决:仅在曲线区域内生效
代码结构

使用环境:QT5.15.1
欢迎批评指正!
曲线
拓展
如果要再添加一条曲线
cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);// 初始化 UI
// 初始化QCustomPlot
customPlot = ui->customPlot1; // 使用UI的customPlot名字而不是创建一个新的。
// 设置 customPlot 以便它接收焦点,确保能够处理事件
customPlot->setFocus();
// 确保QCustomPlot能够接收鼠标事件
customPlot->setFocusPolicy(Qt::StrongFocus); // 设置焦点策略,确保能够接收事件
customPlot->setAttribute(Qt::WA_TransparentForMouseEvents); //避免其他控件(比如按钮、标签等)覆盖在其上面,或者其他控件阻止了事件的传递
// 配置图表
customPlot->addGraph();
customPlot->graph(0)->setPen(QPen(Qt::red)); // 设置曲线1颜色
customPlot->addGraph();
customPlot->graph(1)->setPen(QPen(Qt::blue)); // 设置曲线2颜色
// customPlot->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); // 曲线与X轴包围区的颜色
//设置XY轴的名字
customPlot->xAxis->setLabel("时间 (s)");
customPlot->yAxis->setLabel("相对地面高度");
// 初始化定时器
dataTimer = new QTimer(this);
connect(dataTimer, &QTimer::timeout, this, &MainWindow::updatePlot);
dataTimer->start(20); // 每20毫秒更新一次
// 初始化数据
xData.clear();
yData1.clear();
yData2.clear();
}
注意:1.配置图表时需要再调用一次:customPlot->addGraph();
2.声明变量时需要加曲线2: QVector xData, yData1,yData2; // 数据存储
曲线显示部分修改如下:
cpp
//曲线显示事件
void MainWindow::updatePlot()
{
// 生成新的数据点
// 生成新信号值(如正弦波)
*Value1() = 65 * qSin(*time1());
*time1() += 0.1;
// 生成新信号值(如锯齿)
*count1()+=1;
if(*count1()>75){
*count1()=0;}
*Value2() =*count1();
// 保存数据
xData.append(*time1());
yData1.append(*Value1());
yData2.append(*Value2()); // 这里保存第二条曲线的数据
// 更新图表
customPlot->graph(0)->setData(xData, yData1);
customPlot->graph(1)->setData(xData, yData2);
//这里替换之前的自动缩放
// 自动调整Y轴范围
customPlot->yAxis->rescale(true);
// 更新X轴的范围(保持当前显示区间的时间轴范围)
double lowerX = customPlot->xAxis->range().lower;
double upperX = customPlot->xAxis->range().upper;
// 设置X轴范围,确保X轴根据时间区间自动调整
if (*time1() > upperX) {
customPlot->xAxis->setRange(lowerX + 0.1, upperX + 0.1); // 保持动态显示10秒的数据
}
//刷新数据显示
ui->Hvalue_label->setText(QString::number(*Value1()));
ui->Svalue_label->setText(QString::number(*time1()));
// 刷新图表
customPlot->replot();
}
显示效果如下: