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

使用Customplot绘制时间-数据曲线

从官网下载源码文件

Qt Plotting Widget QCustomPlot - Download

下载后新建工程将对应文件添加到工程

添加模块printsupport

将一个QWidget提升为QCustomplot

部分代码

#include "mainwindow.h"
#include "ui_mainwindow.h"// 生成随机整数[min, max]
static int generateRandomInt(int min, int max) {std::random_device rd;  // 获取随机种子std::mt19937 gen(rd()); // 使用Mersenne Twister引擎std::uniform_int_distribution<> dis(min, max);return dis(gen);
}double generateRandomDouble(double min, double max) {std::random_device rd;std::mt19937 gen(rd());std::uniform_real_distribution<> dis(min, max);return dis(gen);
}static int findClosestDataPointIndex(QCPGraph *graph, double x, double y) {int dataCount = graph->data()->size();if (dataCount == 0) {return -1; // 如果没有数据点,则返回-1}int closestIndex = 0;double minDistance = std::numeric_limits<double>::max();for (int i = 0; i < dataCount; ++i) {double distance = qSqrt(qPow(graph->data()->at(i)->key - x, 2) +qPow(graph->data()->at(i)->value - y, 2));if (distance < minDistance) {minDistance = distance;closestIndex = i;}}return closestIndex;
}MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);ui->listWidget->setSelectionMode(QAbstractItemView::MultiSelection);connect(ui->widget, &QCustomPlot::mousePress, this,&MainWindow::pressGraph);connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,&MainWindow::mouseDoubleClick);
}MainWindow::~MainWindow() {delete ui;
}void MainWindow::pressGraph(QMouseEvent *event) {QCustomPlot *currentPlot = qobject_cast<QCustomPlot *>(QObject::sender());if (!currentPlot) { return; }if (event->button() == Qt::RightButton) {// 获取鼠标点击的坐标QPointF mousePos(event->localPos());// 检查是否点击到了 QCPItemTextQCPAbstractItem *item = currentPlot->itemAt(mousePos, true);if (QCPItemText *textItem = qobject_cast<QCPItemText *>(item)) {// 右键点击到了 QCPItemText,删除该项currentPlot->removeItem(textItem);currentPlot->replot();}return;}if (!ui->mark->isChecked()) { return; }for (int k = 0; k < currentPlot->graphCount(); ++k) {if (currentPlot->plottableAt(event->pos()) == currentPlot->graph(k)) {double x = currentPlot->xAxis->pixelToCoord(event->pos().x());double y = currentPlot->yAxis->pixelToCoord(event->pos().y());int dataPointIndex =findClosestDataPointIndex(currentPlot->graph(k), x, y);double closestX =currentPlot->graph(k)->data()->at(dataPointIndex)->key;double closestY =currentPlot->graph(k)->data()->at(dataPointIndex)->value;// 将X坐标转换为QDateTimeQDateTime dateTime =QDateTime::fromMSecsSinceEpoch(closestX * 1000);// 创建标注点文本m_pointMarkLabel = new QCPItemText(currentPlot);m_pointMarkLabel->setPositionAlignment(Qt::AlignLeft |Qt::AlignVCenter);m_pointMarkLabel->position->setType(QCPItemPosition::ptPlotCoords);m_pointMarkLabel->position->setCoords(closestX, closestY);// 设置文本格式为(2025/08/10 22:12:12.123,22222)QString text =QString("●(%1,%2)").arg(dateTime.toString("yyyy/MM/dd hh:mm:ss.zzz")).arg(closestY, 0, 'f', 0); // 0小数位,不带千分位分隔符m_pointMarkLabel->setText(text);m_pointMarkLabel->setFont(QFont("Arial", 10));m_pointMarkLabel->setPen(QPen(Qt::red));m_pointMarkLabel->setBrush(QBrush(Qt::NoBrush));// 根据Y值调整文本位置偏移,避免重叠double yOffset = (closestY >= 0) ? -10 : 10;m_pointMarkLabel->position->setCoords(closestX, closestY + yOffset);currentPlot->replot();}}
}void MainWindow::mouseDoubleClick(QMouseEvent *event) {QCustomPlot *currentPlot = qobject_cast<QCustomPlot *>(QObject::sender());if (!currentPlot) { return; }currentPlot->rescaleAxes();currentPlot->replot();
}void MainWindow::on_clearSelect_clicked() {}void MainWindow::on_paint_clicked() {QList<QListWidgetItem *> selectedItems = ui->listWidget->selectedItems();for (QListWidgetItem *item : selectedItems) {paintCurve(item->text(), m_data.value(item->text()));}
}void MainWindow::on_generate_clicked() {//生成随机数据m_data.clear();ui->listWidget->clear();int count = generateRandomInt(5, 10);for (int i = 0; i < count; ++i) {QString name = QString("Data_%1").arg(i);qint64 ct = QDateTime::currentMSecsSinceEpoch();int itemCount = generateRandomInt(50, 100);QHash<QDateTime, double> dataHash;for (int j = 0; j < itemCount; ++j) {int step = generateRandomInt(5, 200);ct -= step;dataHash.insert(QDateTime::fromMSecsSinceEpoch(ct),generateRandomDouble(0.0, 6000.00));}m_data.insert(name, dataHash);QListWidgetItem *newItem = new QListWidgetItem;newItem->setText(name);ui->listWidget->addItem(newItem);}
}void MainWindow::on_clearMark_clicked() {ui->widget->clearItems(); // 清除QCustomPlot的所有项,包括QCPItemTextui->widget->replot();
}void MainWindow::on_clearCurve_clicked() {on_clearMark_clicked();ui->widget->clearGraphs();ui->widget->rescaleAxes(); // 自动调整坐标轴到数据范围ui->widget->replot();
}void MainWindow::on_saveCurve_clicked() {QString filePath = QDir::cleanPath(QCoreApplication::applicationDirPath() +QString("Curve_%1.png").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmmsszzz")));ui->widget->savePng(filePath, ui->widget->width(), ui->widget->height());
}void MainWindow::paintCurve(const QString &name,const QHash<QDateTime, double> &data) {QCPGraph *graph = ui->widget->addGraph();graph->setName(name);QVector<double> x, y;auto keys = data.keys();std::sort(keys.begin(), keys.end());for (const auto &time : keys) {double timestamp = time.toMSecsSinceEpoch() / 1000.0; // 转换为秒x.append(timestamp);y.append(data.value(time));}// 设置曲线数据graph->setData(x, y);// 设置随机颜色QColor color(qrand() % 256, qrand() % 256, qrand() % 256);graph->setPen(QPen(color));graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssNone, color, color, 6));ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom |QCP::iSelectPlottables);// 配置坐标轴ui->widget->xAxis->setLabel("时间");QSharedPointer<QCPAxisTickerDateTime> dateTicker(new QCPAxisTickerDateTime);// 2. 设置日期时间格式dateTicker->setDateTimeFormat("yyyy-MM-dd\nhh:mm:ss.zzz");// 3. 将刻度生成器应用到X轴ui->widget->xAxis->setTicker(dateTicker);ui->widget->yAxis->setLabel("数值");// 添加图例ui->widget->legend->setVisible(true);ui->widget->legend->setBrush(QBrush(QColor(255, 255, 255, 150))); // 半透明背景// 自动缩放以显示所有数据ui->widget->rescaleAxes(true);// 刷新绘图ui->widget->replot();
}

运行效果

demon已上传

http://www.dtcms.com/a/469961.html

相关文章:

  • **量子算法:探索未来的发散创新之路**随着信息技术的飞速发展,量子计算作为
  • 4. 手写数字识别,推理,批处理
  • AI编程时代的文档困境与破局之道:从Cursor到完整开发体系
  • DVWA靶场之十八:API 安全(API Security)
  • ORB_SLAM2原理及代码解析:Optimizer::LocalBundleAdjustment
  • 中文wordpress站点wordpress 获取路径
  • 从零搭建 Kubernetes 1.28 高可用集群
  • 网站建设有什么岗位职责唐山广告设计制作公司
  • Apache Doris 内部数据裁剪与过滤机制的实现原理 | Deep Dive
  • 长沙百度网站建设专精特新中小企业
  • 网站上广告wordpress导出文章word
  • Voron Trident 三叉戟 组装日记
  • 南昌公司做网站网站建设湖南岚鸿建设
  • “零成本自由派”与“钉钉生态派”:斑斑与氚云的选择
  • Flutter 仿网易云音乐播放器:唱片旋转 + 歌词滚动实现记录
  • 编写Python脚本在域名过期10天内将域名信息发送到钉钉
  • Flutter 开发环境安装
  • 中科时代建设官方网站设计品牌logo
  • 【C++】模板 - - - 泛型编程的魔法模具,一键生成各类代码
  • Vue3知识详解(一)(基础知识部分)
  • 网站网页链接网站变灰色 html
  • Docker核心技术:深入理解网络模式 ——Bridge模式全栈实战与性能调优
  • Spring Web MVC构建现代Java Web应用的基石
  • 如何做tiktok的数据排行网站手机网站页面大小
  • 单片机睡眠模式详解:睡眠、停止与待机
  • 长春做网站公司哪家好做统计图的网站
  • 【Android Gradle学习笔记】第一天:认识下Gradle
  • 一级a做爰片免费网站孕交视频教程wordpress添加作者名字
  • 《基础算法递归-----汉诺塔问题》
  • 网站前台设计模板荆州网站建设 松滋网站建设