news 2026/4/20 11:03:24

QT Creator + QCustomPlot:手把手教你打造一个能保存图片的WIFI数据绘图上位机

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
QT Creator + QCustomPlot:手把手教你打造一个能保存图片的WIFI数据绘图上位机

QT Creator + QCustomPlot:从零构建支持多格式保存的WIFI数据可视化上位机

在嵌入式开发和物联网应用中,数据可视化是调试和分析的关键环节。一个功能完善的上位机不仅能实时显示传感器数据,还能将关键图表持久化保存,这对研发文档整理和问题回溯至关重要。本文将带你用QT Creator和QCustomPlot库,打造一个能通过WIFI接收数据、实时绘制曲线,并支持PNG/JPG/PDF等多种格式保存的专业级上位机。

1. 开发环境搭建与项目初始化

1.1 QT Creator安装与配置

QT Creator作为跨平台的C++开发环境,建议选择5.15 LTS版本以获得最佳稳定性。安装时需注意:

  • 勾选Qt ChartsQt Network模块
  • 配置MSVC或MinGW编译器(Windows平台)
  • 设置合适的QT版本路径和工具链

验证安装成功的简单方法:

qmake -v # 应输出类似:QMake version 3.1

1.2 QCustomPlot库集成

QCustomPlot是QT生态中强大的2D绘图库,集成步骤:

  1. 下载最新源码包(当前推荐2.1.1版本)
  2. qcustomplot.hqcustomplot.cpp添加到项目
  3. 在.pro文件中添加打印支持:
QT += printsupport

测试集成是否成功:

#include "qcustomplot.h" // ... QCustomPlot *plot = new QCustomPlot(this); plot->addGraph(); plot->graph(0)->setData(xData, yData); plot->replot();

2. WIFI通信模块设计与实现

2.1 TCP服务端搭建

上位机通常作为TCP服务端运行,核心代码如下:

// 在头文件中声明 QTcpServer *tcpServer; QTcpSocket *tcpSocket; // 初始化服务器 tcpServer = new QTcpServer(this); if(!tcpServer->listen(QHostAddress::Any, 1234)) { qDebug() << "Server could not start"; } else { qDebug() << "Server started!"; connect(tcpServer, &QTcpServer::newConnection, this, &MainWindow::newConnection); } void MainWindow::newConnection() { tcpSocket = tcpServer->nextPendingConnection(); connect(tcpSocket, &QTcpSocket::readyRead, this, &MainWindow::readData); connect(tcpSocket, &QTcpSocket::disconnected, this, &MainWindow::clientDisconnected); }

2.2 数据协议设计与解析

为增强健壮性,建议采用JSON格式传输数据:

{ "timestamp": 1630000000, "sensor_id": "temp_001", "values": [22.5, 22.6, 22.4] }

对应的解析代码:

void MainWindow::readData() { QByteArray data = tcpSocket->readAll(); QJsonDocument doc = QJsonDocument::fromJson(data); if(doc.isNull()) { qDebug() << "Invalid JSON format"; return; } QJsonObject obj = doc.object(); QVector<double> values; for(auto v : obj["values"].toArray()) { values.append(v.toDouble()); } // 更新图表... }

3. 数据可视化与图表交互

3.1 实时曲线绘制优化

QCustomPlot的实时显示需要特殊处理:

// 初始化图表 customPlot->addGraph(); customPlot->xAxis->setLabel("Time(s)"); customPlot->yAxis->setLabel("Value"); customPlot->xAxis->setRange(0, 10); customPlot->yAxis->setRange(-1, 1); // 定时刷新 QTimer *dataTimer = new QTimer(this); connect(dataTimer, &QTimer::timeout, [=](){ static double lastPointKey = 0; double value = getNewValue(); // 获取新数据 customPlot->graph(0)->addData(lastPointKey, value); lastPointKey += 0.1; // 自动滚动显示 customPlot->xAxis->setRange(lastPointKey, 10, Qt::AlignRight); customPlot->replot(); }); dataTimer->start(100); // 10Hz刷新

3.2 多图表协同显示

实现多曲线对比显示:

// 添加第二条曲线 customPlot->addGraph(); customPlot->graph(1)->setPen(QPen(Qt::red)); // 数据更新时 customPlot->graph(0)->setData(xData1, yData1); customPlot->graph(1)->setData(xData2, yData2); customPlot->rescaleAxes(); customPlot->replot();

4. 图表导出与高级功能实现

4.1 多格式保存功能

完善的文件保存对话框实现:

void MainWindow::on_saveButton_clicked() { QString filter = "PNG (*.png);;JPEG (*.jpg *.jpeg);;PDF (*.pdf);;BMP (*.bmp)"; QString fileName = QFileDialog::getSaveFileName(this, "Save Plot", QStandardPaths::writableLocation(QStandardPaths::PicturesLocation), filter); if(fileName.isEmpty()) return; bool saved = false; if(fileName.endsWith(".png", Qt::CaseInsensitive)) { saved = customPlot->savePng(fileName); } else if(fileName.endsWith(".jpg", Qt::CaseInsensitive) || fileName.endsWith(".jpeg", Qt::CaseInsensitive)) { saved = customPlot->saveJpg(fileName); } else if(fileName.endsWith(".pdf", Qt::CaseInsensitive)) { saved = customPlot->savePdf(fileName); } else if(fileName.endsWith(".bmp", Qt::CaseInsensitive)) { saved = customPlot->saveBmp(fileName); } if(saved) { statusBar()->showMessage("Saved to " + fileName, 3000); } else { QMessageBox::warning(this, "Error", "Failed to save image"); } }

4.2 高DPI支持与打印功能

现代显示器需要高DPI适配:

// 在main.cpp中 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // 打印功能实现 void MainWindow::on_printButton_clicked() { QPrinter printer(QPrinter::HighResolution); QPrintDialog dialog(&printer, this); if(dialog.exec() == QDialog::Accepted) { QPainter painter(&printer); QRect rect = painter.viewport(); QSize size = customPlot->size(); size.scale(rect.size(), Qt::KeepAspectRatio); painter.setViewport(rect.x(), rect.y(), size.width(), size.height()); painter.setWindow(customPlot->rect()); customPlot->render(&painter); } }

5. 项目打包与部署

5.1 Windows平台打包

使用windeployqt工具自动收集依赖:

windeployqt --release --compiler-runtime your_app.exe

5.2 Linux平台打包

创建.desktop桌面入口文件:

[Desktop Entry] Version=1.0 Type=Application Name=WIFI Plotter Exec=/usr/bin/wifi_plotter Icon=wifi-plotter Comment=WIFI Data Visualization Tool Categories=Utility;

实际开发中发现,将QCustomPlot的渲染模式设置为QPaintDevice::HighQuality能显著提升导出图像的质量,特别是在PDF格式下。对于长时间运行的监控应用,建议实现数据缓存机制,避免内存无限增长。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 10:58:18

别再只会用tf了!Matlab feedback函数实战:从单回路到MIMO系统,手把手教你搭建控制系统模型

从单回路到MIMO系统&#xff1a;Matlab feedback函数的高阶实战指南 控制系统工程师常常陷入一个思维定式——将反馈系统简化为单输入单输出(SISO)模型来处理。这种简化在学术练习中或许足够&#xff0c;但在面对无人机姿态控制、工业机器人多关节协同等真实场景时&#xff0c;…

作者头像 李华
网站建设 2026/4/20 10:53:06

YOLO12快速部署:替换端口即可访问https://gpu-xxx-7860.web.gpu.csdn.net/

YOLO12快速部署&#xff1a;替换端口即可访问https://gpu-xxx-7860.web.gpu.csdn.net/ 1. YOLO12&#xff1a;新一代目标检测的革命性突破 YOLO12是2025年最新发布的目标检测模型&#xff0c;由美国纽约州立大学布法罗分校和中国科学院大学联合研发。这个模型带来了革命性的注…

作者头像 李华
网站建设 2026/4/20 10:51:11

从JustTrustMe模块入手,5分钟搞懂Android SSL证书验证的Hook原理与绕过

从JustTrustMe模块入手&#xff0c;5分钟搞懂Android SSL证书验证的Hook原理与绕过 在移动应用安全测试领域&#xff0c;SSL证书验证是一个绕不开的话题。想象一下&#xff0c;当你正在对一款金融类APP进行安全评估时&#xff0c;突然发现所有HTTPS请求都无法正常抓包分析——这…

作者头像 李华