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

QCustomPlot 高级扩展与实战案例

QCustomPlot 高级扩展与实战案例

在掌握了 QCustomPlot 的基础使用、样式定制、性能优化之后,我们进入更高阶的应用阶段。本文将带你深入 自定义坐标轴、图表注释、打印集成,并通过两个完整实战案例(实时监控系统、Qt Quick 跨界面展示)展示其工程价值。最后,我们将简要剖析 QCustomPlot 源码结构,为深度定制提供思路。


1. 自定义坐标轴:实现对数轴、时间轴(日期/时间格式)

对数坐标轴(Logarithmic Axis)

QCustomPlot 原生支持对数刻度,只需设置轴类型:

plot->yAxis->setScaleType(QCPAxis::stLogarithmic);
plot->yAxis->setNumberFormat("eb"); // e:科学计数法, b:自动底数
plot->yAxis->setNumberPrecision(0);
plot->yAxis->setRange(1e-2, 1e3); // 注意:对数轴不能包含 0 或负数

⚠️ 注意:数据必须全部为正数,否则会引发渲染异常。

时间轴(日期/时间格式)

QCustomPlot 本身不直接支持 QDateTime,但可通过 将时间转换为秒/毫秒数值,再自定义刻度标签实现。

// 数据准备:时间戳(秒)
QVector<double> timestamps;
QVector<double> values;
for (int i = 0; i < 100; ++i) {timestamps << QDateTime::currentSecsSinceEpoch() - (100 - i) * 60; // 近100分钟values << qSin(i * 0.1) * 10 + 20;
}// 设置 X 轴为时间轴
plot->xAxis->setTickLabelType(QCPAxis::ltDateTime);
plot->xAxis->setDateTimeFormat("hh:mm\ndd/MM");
plot->xAxis->setDateTimeSpec(Qt::LocalTime); // 或 Qt::UTCplot->addGraph();
plot->graph(0)->setData(timestamps, values);
plot->rescaleAxes();

✅ 提示:setDateTimeFormat() 支持 Qt 的标准日期格式,如 "yyyy-MM-dd hh:mm"


2. 图表标注与注释:添加文本标注、箭头、矩形框等辅助元素

QCustomPlot 提供丰富的 QCPAbstractItem 子类用于标注。

添加文本标注

QCPItemText *text = new QCPItemText(plot);
text->setPositionAlignment(Qt::AlignTop | Qt::AlignLeft);
text->position->setType(QCPItemPosition::ptPlotCoords);
text->position->setCoords(x, y); // 图表坐标
text->setText("峰值点");
text->setFont(QFont("Arial", 10, QFont::Bold));
text->setColor(Qt::red);

添加箭头(带文本)

QCPItemLine *arrow = new QCPItemLine(plot);
arrow->start->setType(QCPItemPosition::ptPlotCoords);
arrow->end->setType(QCPItemPosition::ptPlotCoords);
arrow->start->setCoords(x1, y1);
arrow->end->setCoords(x2, y2);
arrow->setHead(QCPLineEnding::esSpikeArrow); // 箭头样式// 可与文本组合使用

添加矩形高亮区域

QCPItemRect *rect = new QCPItemRect(plot);
rect->topLeft->setType(QCPItemPosition::ptPlotCoords);
rect->bottomRight->setType(QCPItemPosition::ptPlotCoords);
rect->topLeft->setCoords(x1, y1);
rect->bottomRight->setCoords(x2, y2);
rect->setBrush(QColor(255, 255, 0, 50)); // 半透明黄色
rect->setPen(Qt::NoPen);

💡 所有 QCPItem 默认随图表缩放/平移自动调整位置。


3. 图表打印功能:将 QCustomPlot 图表集成到 Qt 打印模块

QCustomPlot 内置对 QPrinter 的支持,可直接打印或预览。

打印预览对话框

#include <QPrintPreviewDialog>
#include <QPrinter>void printPlot(QCustomPlot *plot) {QPrinter printer(QPrinter::HighResolution);QPrintPreviewDialog preview(&printer);connect(&preview, &QPrintPreviewDialog::paintRequested, [=](QPrinter *p) {plot->toPainter(p, plot->width(), plot->height());});preview.exec();
}

直接打印

QPrinter printer;
printer.setPageOrientation(QPageLayout::Landscape);
plot->print(&printer);

✅ 优势:打印输出为矢量(PDF)或高分辨率位图,文字清晰不模糊。


4. 实战案例(一):基于 QCustomPlot 的实时数据监控系统

需求

  • 实时显示 3 路传感器数据(温度、湿度、压力)
  • 支持缩放、平移、重置
  • 超限报警(红色高亮)
  • 每秒更新 10 次

核心代码结构

class RealTimeMonitor : public QMainWindow {QCustomPlot *plot;QTimer *timer;QVector<double> timeBuffer;QVector<QVector<double>> dataBuffers; // [3][N]public:RealTimeMonitor() {plot = new QCustomPlot(this);setCentralWidget(plot);// 初始化三条曲线for (int i = 0; i < 3; ++i) {plot->addGraph();dataBuffers.append(QVector<double>());}plot->graph(0)->setPen(Qt::red);plot->graph(1)->setPen(Qt::green);plot->graph(2)->setPen(Qt::blue);// 交互plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);// 定时器timer = new QTimer(this);connect(timer, &QTimer::timeout, this, &RealTimeMonitor::updateData);timer->start(100); // 10Hz}void updateData() {double t = QDateTime::currentMSecsSinceEpoch() / 1000.0;timeBuffer.append(t);for (int i = 0; i < 3; ++i) {double val = simulateSensor(i); // 模拟数据dataBuffers[i].append(val);// 超限检查if (val > thresholds[i]) {plot->graph(i)->setPen(QPen(Qt::red, 2));}}// 滚动窗口:保留最近 100 点if (timeBuffer.size() > 100) {timeBuffer.remove(0);for (auto &buf : dataBuffers) buf.remove(0);}// 更新数据for (int i = 0; i < 3; ++i) {plot->graph(i)->setData(timeBuffer, dataBuffers[i]);}plot->xAxis->setRange(t - 10, t + 1); // 动态跟随plot->replot();}
};

✅ 此架构可轻松扩展为多通道工业监控系统。


5. 实战案例(二):QCustomPlot + Qt Quick 的跨界面图表展示

虽然 QCustomPlot 是 QWidget 控件,但可通过 QWidget::createWindowContainer 嵌入 Qt Quick。

步骤

  1. 创建一个继承 QQuickPaintedItem 的封装类(不推荐,性能差);
  2. 推荐方案:使用 QQuickWidgetQWidget::createWindowContainer

示例:在 QML 中嵌入 QCustomPlot

// main.cpp
QQmlApplicationEngine engine;
QCustomPlot *plot = new QCustomPlot();
// ... 配置 plot// 创建容器
QWidget *container = QWidget::createWindowContainer(plot, nullptr, Qt::Widget);
container->setMinimumSize(600, 400);// 注册为 QML 类型
engine.rootContext()->setContextProperty("plotWidget", container);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15ApplicationWindow {visible: truewidth: 800; height: 600Column {anchors.centerIn: parentText { text: "QCustomPlot in QML" }// 嵌入 QWidget 容器Rectangle {width: 600; height: 400color: "transparent"Component.onCompleted: {// 通过 C++ 设置的 context property 添加var widget = plotWidgetparent.parent.contentItem.appendChild(widget)}}}
}

⚠️ 注意:此方法在 macOS/Linux 下可能有窗口嵌套问题,建议在纯 QWidget 应用中使用 QCustomPlot,或改用 Qt Charts(原生 QML 支持)。


6. 进阶:QCustomPlot 源码解读(核心渲染逻辑与扩展思路)

源码结构概览

  • qcustomplot.h/cpp:核心类定义
  • QCustomPlot:主控件,负责布局、事件、重绘调度
  • QCPLayer:图层系统(背景、网格、主图、前景等)
  • QCPAbstractPlottable:所有可绘图对象的基类(如 QCPGraph, QCPBars
  • QCPAxis / QCPAxisRect:坐标轴与绘图区域
  • QCPAbstractItem:标注元素基类

渲染流程

  1. 调用 replot()
  2. 清空各图层;
  3. 依次调用各 plottable 的 draw() 方法;
  4. 绘制坐标轴、网格、图例;
  5. 合成最终图像。

扩展思路

  • 自定义 Plottable:继承 QCPAbstractPlottable,重写 draw()selectTest()
  • 自定义 AxisTicker:实现特殊刻度逻辑(如股票 K 线时间轴);
  • 自定义 Item:绘制复杂标注(如带背景的标签、多段箭头)。

示例:自定义 Plottable(简易)

class MyCustomPlot : public QCPAbstractPlottable {
public:MyCustomPlot(QCPAxis *keyAxis, QCPAxis *valueAxis) : QCPAbstractPlottable(keyAxis, valueAxis) {}void draw(QCPPainter *painter) override {// 自定义绘制逻辑painter->setPen(mainPen());painter->drawLine(...);}QRect clipRect() const override { return ...; }void selectTest(...) override { /* 选择检测 */ }
};

📚 建议阅读官方文档中的 “Creating Custom Plottables” 章节。


结语

通过本文,你已掌握 QCustomPlot 的高级扩展能力:

  • 灵活定制坐标轴(对数、时间);
  • 丰富图表注释提升信息密度;
  • 无缝集成打印与报告系统;
  • 构建实时监控等工业级应用;
  • 在混合界面(Qt Quick)中谨慎使用;
  • 具备源码级扩展能力。

QCustomPlot 虽为“轻量级”,但其设计精巧、扩展性强,足以支撑复杂可视化需求。善用其架构,你将能打造出媲美商业软件的专业图表系统。

最后建议:对于新项目,若需深度 QML 集成,可评估 Qt Charts;若追求性能与定制自由,QCustomPlot 仍是不二之选。

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

相关文章:

  • C语言形式参数和实际参数的区别(附带示例)
  • 医疗领域的数智化转型与智能化变革研究报告:技术驱动、模式创新与政策协同
  • 在 C# 中,如何使 $““ 字符串支持换行
  • 2025年精选单北斗GNSS水库形变监测系统对比推荐
  • Java 在Word 文档中添加批注:高效文档协作的利器
  • 代做效果图网站项目管理软件的作用
  • 广东省高水平建设专业网站北京大兴网站建设
  • 使用 HBuilderX 将网页打包为安卓 APP详细步骤
  • MinerU2.5:一种用于高效高分辨率文档解析的解耦视觉-语言模型
  • Redis三大命令分类详解
  • 饼状图修复总结
  • npm 最新镜像,命令导致下载错误
  • 济宁做公司网站中职电子商务专业就业方向
  • JVM深入研究--JHSDB (jvm 分析工具)
  • AI的局限性,有所能与有所不能
  • 广州网站设计公司推荐哪家网站的风格设计有哪些
  • 【完整源码+数据集+部署教程】武装人员图像分割系统: yolov8-seg-GFPN
  • 开发避坑指南(61):Redis持久化失败:RDB快照因磁盘问题无法保存解决方案
  • 短视频网站如何做推广网站导航栏最多可以做几个
  • 做自由行的网站广告运营推广
  • 逆向爬虫——JavaScript混淆技术
  • 4.0 Labview中算法实例1-迟滞曲线上两段的平均差(拐点计算)
  • 网站建设数据库搭建西安广告设计制作公司
  • 作一手房用什么做网站有关学校网站建设策划书
  • 企业网站建设方案详细方案厦门网站建设2
  • 微服务服务治理
  • 网站定制费用银川建设网站
  • [陇剑杯 2021]简单日志分析(问3)
  • 微信的网站徐州网站设计师
  • CC工具箱使用指南:【整库修复几何】