探索基于QCustomPlot的强大数据可视化工具

qcustomplot曲线图,数据可视化分析工具源码;加载excel和xml数据展示,数据接口可很方便扩展,数据展示具备多条曲线同时窗口展示,支持多窗口的鼠标同步操作(滚轮缩放,左键平移,右键框选等功能),添加阈值线-计算范围值;支持属性面板设置曲线样式,窗口布局类似于vs可以隐藏/显示dock窗口;代码可以扩展,采用qt5.9环境开发;

在数据驱动的时代,高效的数据可视化对于理解和分析数据至关重要。今天咱就来唠唠一个基于QCustomPlot开发的数据可视化分析工具,它功能那叫一个丰富,源码在手,探索不愁。

一、整体框架与开发环境

这个工具基于Qt5.9环境开发。Qt可是个好东西,跨平台能力一流,让咱开发效率蹭蹭往上涨。为啥选Qt5.9呢?稳定呀,很多功能已经相当成熟,对各种系统的适配也很到位。

二、数据加载

1. Excel数据加载

加载Excel数据,极大地方便了从常见办公数据文件中获取信息。在Qt中,咱可以借助第三方库如QAxObject来实现Excel数据读取。以下是一段简单示例代码:

cpp 复制代码
#include <QAxObject>
void loadExcelData(const QString& filePath) {
    QAxObject excel("Excel.Application");
    excel.setProperty("Visible", false);
    QAxObject* workbooks = excel.querySubObject("Workbooks");
    QAxObject* workbook = workbooks->querySubObject("Open(const QString&)", filePath);
    QAxObject* worksheet = workbook->querySubObject("Sheets(int)", 1);
    QAxObject* usedRange = worksheet->querySubObject("UsedRange");
    QAxObject* rows = usedRange->querySubObject("Rows");
    int rowCount = rows->property("Count").toInt();
    QAxObject* columns = usedRange->querySubObject("Columns");
    int columnCount = columns->property("Count").toInt();

    for (int i = 1; i <= rowCount; ++i) {
        for (int j = 1; j <= columnCount; ++j) {
            QAxObject* cell = worksheet->querySubObject("Cells(int, int)", i, j);
            QVariant cellValue = cell->dynamicCall("Value");
            // 这里可以将cellValue处理后存储到你的数据结构中
            qDebug() << cellValue;
            cell->deleteLater();
        }
    }

    workbook->dynamicCall("Close()");
    workbooks->deleteLater();
    excel.dynamicCall("Quit()");
    excel.deleteLater();
}

代码分析:首先创建了一个Excel应用程序对象,并设置其不可见。然后通过Workbooks对象打开指定的Excel文件,获取第一个工作表。接着确定使用范围的行列数,遍历每个单元格获取其值。最后关闭工作簿、工作簿集合以及Excel应用程序。

2. XML数据加载

XML也是常用的数据存储格式,Qt提供了QXmlStreamReader来方便地解析XML数据。示例代码如下:

cpp 复制代码
#include <QFile>
#include <QXmlStreamReader>
void loadXmlData(const QString& filePath) {
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Could not open file";
        return;
    }
    QXmlStreamReader xmlReader(&file);
    while (!xmlReader.atEnd() &&!xmlReader.hasError()) {
        QXmlStreamReader::TokenType token = xmlReader.readNext();
        if (token == QXmlStreamReader::StartDocument) {
            continue;
        }
        if (token == QXmlStreamReader::StartElement) {
            if (xmlReader.name() == "data") {
                // 处理data元素下的子元素
                while (!(xmlReader.atEnd() || xmlReader.hasError()) && (token = xmlReader.readNext())!= QXmlStreamReader::EndElement) {
                    if (token == QXmlStreamReader::StartElement) {
                        if (xmlReader.name() == "item") {
                            QString value = xmlReader.attributes().value("value").toString();
                            // 这里可以将value处理后存储到你的数据结构中
                            qDebug() << value;
                        }
                    }
                }
            }
        }
    }
    if (xmlReader.hasError()) {
        qDebug() << "XML parsing error: " << xmlReader.errorString();
    }
    file.close();
}

代码分析:打开XML文件后,通过QXmlStreamReader逐行读取。遇到开始文档标记就跳过,遇到开始元素标记时,如果是"data"元素,就进一步处理其下的"item"子元素,并获取"value"属性值。最后检查是否有解析错误并关闭文件。

三、数据展示

1. 多曲线同时展示

QCustomPlot是实现多曲线展示的利器。下面看看如何在窗口中同时展示多条曲线:

cpp 复制代码
#include "qcustomplot.h"
void setupMultiCurvePlot(QCustomPlot* customPlot) {
    QVector<double> x(101), y1(101), y2(101);
    for (int i = 0; i < 101; ++i) {
        x[i] = i / 10.0;
        y1[i] = sin(x[i]);
        y2[i] = cos(x[i]);
    }
    customPlot->addGraph();
    customPlot->graph(0)->setData(x, y1);
    customPlot->graph(0)->setPen(QPen(Qt::blue));

    customPlot->addGraph();
    customPlot->graph(1)->setData(x, y2);
    customPlot->graph(1)->setPen(QPen(Qt::red));

    customPlot->xAxis->setLabel("X Axis");
    customPlot->yAxis->setLabel("Y Axis");
    customPlot->replot();
}

代码分析:先创建了三个QVector分别存储x轴数据以及两条曲线的y轴数据。通过addGraph方法添加两条曲线,分别设置数据和画笔颜色。最后设置坐标轴标签并重新绘制图表。

2. 多窗口鼠标同步操作

实现多窗口鼠标同步操作,让用户在不同窗口间能以相同的交互方式查看数据。以滚轮缩放为例,在每个窗口的鼠标滚轮事件处理函数中:

cpp 复制代码
void MainWindow::wheelEvent(QWheelEvent* event) {
    if (event->delta() > 0) {
        ui->customPlot->xAxis->scaleRange(0.9, ui->customPlot->xAxis->range().center());
        ui->customPlot->yAxis->scaleRange(0.9, ui->customPlot->yAxis->range().center());
    } else {
        ui->customPlot->xAxis->scaleRange(1.1, ui->customPlot->xAxis->range().center());
        ui->customPlot->yAxis->scaleRange(1.1, ui->customPlot->yAxis->range().center());
    }
    ui->customPlot->replot();
    // 同步到其他窗口,这里假设还有一个customPlot2
    ui->customPlot2->xAxis->scaleRange(ui->customPlot->xAxis->scaleFactor(), ui->customPlot->xAxis->range().center());
    ui->customPlot2->yAxis->scaleRange(ui->customPlot->yAxis->scaleFactor(), ui->customPlot->yAxis->range().center());
    ui->customPlot2->replot();
}

代码分析:根据滚轮滚动方向,对当前窗口的坐标轴进行缩放,然后重新绘制。接着将缩放比例同步到其他窗口并重新绘制。左键平移和右键框选功能实现思路类似,都是通过获取鼠标事件的坐标信息,计算相应的偏移量或区域,然后应用到各个窗口的图表上。

3. 添加阈值线 - 计算范围值

添加阈值线能直观地显示数据与设定值的关系。以下是添加阈值线的代码:

cpp 复制代码
void addThresholdLine(QCustomPlot* customPlot, double threshold) {
    QCPItemLine* thresholdLine = new QCPItemLine(customPlot);
    thresholdLine->start->setCoords(customPlot->xAxis->range().lower, threshold);
    thresholdLine->end->setCoords(customPlot->xAxis->range().upper, threshold);
    thresholdLine->setPen(QPen(Qt::green, 1, Qt::DashLine));
}

代码分析:创建一个QCPItemLine对象,设置其起点和终点的坐标,使其跨越整个x轴范围且y坐标为设定的阈值。同时设置画笔为绿色虚线,这样就添加好了阈值线。计算范围值可以通过获取图表数据的最值来实现,比如:

cpp 复制代码
double minY = ui->customPlot->graph(0)->data()->at(0).value;
double maxY = ui->customPlot->graph(0)->data()->at(0).value;
for (int i = 1; i < ui->customPlot->graph(0)->data()->size(); ++i) {
    double value = ui->customPlot->graph(0)->data()->at(i).value;
    if (value < minY) {
        minY = value;
    }
    if (value > maxY) {
        maxY = value;
    }
}
double rangeValue = maxY - minY;

代码分析:先初始化最小值和最大值为第一条曲线的第一个数据点的值,然后遍历曲线数据,更新最小值和最大值,最后计算范围值。

四、属性面板与窗口布局

1. 属性面板设置曲线样式

通过属性面板可以灵活地调整曲线样式。比如,在属性面板中选择曲线颜色,然后更新图表曲线颜色的代码:

cpp 复制代码
void MainWindow::on_colorComboBox_currentIndexChanged(int index) {
    QColor color = QColorDialog::customColor(index);
    ui->customPlot->graph(0)->setPen(QPen(color));
    ui->customPlot->replot();
}

代码分析:当颜色选择框的索引改变时,获取对应的颜色,设置到第一条曲线上并重新绘制图表。

2. 类似VS的窗口布局

采用Qt的QDockWidget来实现类似VS的窗口布局,可以方便地隐藏/显示dock窗口。

cpp 复制代码
QDockWidget* dockWidget = new QDockWidget("Data Panel", this);
QWidget* dockWidgetContents = new QWidget();
// 在dockWidgetContents中添加各种控件,比如属性面板的控件
dockWidget->setWidget(dockWidgetContents);
addDockWidget(Qt::RightDockWidgetArea, dockWidget);

代码分析:创建一个QDockWidget对象,并设置其标题。然后创建一个内容部件,将其设置为dock窗口的部件,最后将dock窗口添加到主窗口的右侧停靠区域。

五、代码扩展性

整个工具的代码设计得很有扩展性。比如数据接口部分,若要添加新的数据来源,只需要按照现有数据加载的模式,实现新的数据读取逻辑并集成到数据加载模块中。像前面提到的Excel和XML数据加载,都是相对独立的模块,新的数据加载方式也可以以类似方式加入,不会对其他部分造成太大影响。

qcustomplot曲线图,数据可视化分析工具源码;加载excel和xml数据展示,数据接口可很方便扩展,数据展示具备多条曲线同时窗口展示,支持多窗口的鼠标同步操作(滚轮缩放,左键平移,右键框选等功能),添加阈值线-计算范围值;支持属性面板设置曲线样式,窗口布局类似于vs可以隐藏/显示dock窗口;代码可以扩展,采用qt5.9环境开发;

总之,这个基于QCustomPlot的数据可视化分析工具,从数据加载到展示,再到用户交互和布局设置,功能丰富且代码具备良好的扩展性,在实际的数据处理和分析场景中能发挥大作用。希望大家可以基于它进行更多有趣的开发和探索。

相关推荐
赵渝强老师3 小时前
【赵渝强老师】Oracle多租户容器数据库
数据库·oracle
hunter14504 小时前
2026.1.20 sql server简单操作
数据库·oracle
达梦产品与服务4 小时前
SQLark 实战 | 如何快速导入数据至达梦、Oracle、MySQL、PG 数据库
mysql·oracle·达梦数据库·数据导入·pg数据库
小天源8 小时前
Oracle Database 11g Express Edition (XE) 11.2.0.2 在离线银河麒麟 V10 上的部署手册
数据库·oracle·express·麒麟v10·oracle11g·oracle-xe-11g
全栈小59 小时前
【数据库】Oracle数据库迁移的深层痛点:兼容性、成本与隐性挑战
数据库·oracle
人道领域9 小时前
javaWeb从入门到进阶(MYSQL)
数据库·mysql·oracle
知识分享小能手10 小时前
Oracle 19c入门学习教程,从入门到精通,Oracle 数据表对象 —— 语法知识点详解与案例实践(10)
数据库·学习·oracle
Navicat中国10 小时前
Navicat Premium MacOS:原生或通过 Rosetta 运行教程
数据库·macos·oracle·navicat·rosetta
阿坤带你走近大数据10 小时前
Oracle存储过程与触发器的详细介绍
数据库·oracle