当前位置: 首页 > article >正文

【QT】】qcustomplot的初步使用二

功能预期:

在简单显示曲线()基础上加功能:
1.在曲线区域里,X轴可以随鼠标滚轮变化将图像缩放、随鼠标左键进行曲线移动;
2.在曲线区域里,Y轴的量程可以随Y轴数据大小自适应;
3.可以动态显示最新的数据。
4.拓展:再增加一条曲线同时显示
在这里插入图片描述

代码实现

具体细节已在注释中标记清楚
mainwindow.h

#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

#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

#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
欢迎批评指正!

曲线

拓展

如果要再添加一条曲线

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; // 数据存储

曲线显示部分修改如下:

//曲线显示事件
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();
}

显示效果如下:
在这里插入图片描述


http://www.kler.cn/a/593294.html

相关文章:

  • 欢乐力扣:基本计算器
  • 阿里云 AI 搜索产品荣获 Elastic Innovation Award 2024
  • 合法C标识符查(信息学奥赛一本通-1134)
  • 理解PyTorch 张量的多维张量索引
  • 【Docker】- Dockerfile和Docker Compose 基础配置
  • sqlite mmap
  • 离散概率分布:正态分布,二项分布,连续分布,正态分布的性质
  • 51单片机和STM32 入门分析
  • 【electron】vue项目中使用electron打包报错的解决办法
  • Python基础入门掌握(十四)
  • 【OCR】总结github上开源 OCR 工具:让文字识别更简单
  • 【初始C语言】转义字符
  • 使用DDR4控制器实现多通道数据读写(四)
  • sass介绍
  • 跨境大文件传输如何突破延迟与丢包双重困局
  • Git——分布式版本控制工具使用教程
  • 分享下web3j 常见用法
  • Windows主机、虚拟机Ubuntu、开发板,三者之间文件互传
  • RabbitMQ常见面试题及解析
  • 开源!我整理了50个ChatGPT插件开发案例