QChart绘制折线图

1、前言

记录一下QChart绘制折线图点的实现方法,方便自己会顾,也可以给有需要的人提供帮助。

2、QChart绘制折线图实现步骤

2.1 在.pro文件中添加charts模块

QT       += core gui serialport serialbus charts

在这里插入图片描述

2.2 添加头文件

#include <QWidget>
#include <QtCharts>
#include <QPoint>
#include <QLineSeries>
#include <QValueAxis>
#include <QPoint>
#include <QChartView>

QT_CHARTS_USE_NAMESPACE

在这里插入图片描述

2.3 创建图表对象和相关组件

QChart *chart;               //图表对象
QValueAxis *axisX;          //x轴
QValueAxis *axisY;          //y轴
QLineSeries *series;         //折线图
QElapsedTimer  startTimer; // 记录图表开始时间

在这里插入图片描述

2.4 初始化图表对象和相关组件

//初始化
chart = new QChart();           // 创建图表对象
axisX = new QValueAxis();       // 创建X轴(时间轴)
axisY = new QValueAxis();       // 创建Y轴(流量轴)
series = new QLineSeries();     // 创建折线系列用于绘制数据

在这里插入图片描述

2.5 配置x轴和y轴

 // 配置X轴属性
 axisX->setTitleText("时间(s)");     // 设置X轴标题
 axisX->setLabelFormat("%d");        // 设置X轴标签格式为整数
 axisX->setRange(0,60);              // 设置X轴初始范围为0-60秒
 
 // 配置Y轴属性
 axisY->setTitleText("流量 (mL/min)"); // 设置Y轴标题
 axisY->setLabelFormat("%.1f");        // 设置Y轴标签格式为1位小数
 axisY->setRange(100, 600);           // 设置Y轴初始范围为100-600mL/min

2.6 将系列添加到图表

chart->addSeries(series);  // 将折线系列添加到图表容器

注:必须在添加坐标轴前将系列加入图表

2.7 将坐标轴添加到图表

chart->addAxis(axisX,Qt::AlignBottom); // X轴放置在底部
chart->addAxis(axisY,Qt::AlignLeft);   // Y轴放置在左侧

2.8 将系列附加到坐标轴

series->attachAxis(axisX);  // 关联X轴
series->attachAxis(axisY);  // 关联Y轴

2.9 配置图表属性

chart->setTitle("流量实时曲线");         // 设置图表标题
chart->setAnimationOptions(QChart::NoAnimation); // 禁用动画提高性能
chart->legend()->show();               // 显示图例

2.10 创建图表视图

QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing); // 启用抗锯齿

2.11 设置布局显示

QVBoxLayout *layout = new QVBoxLayout(this);  // 创建垂直布局管理器
layout->addWidget(chartView);                 // 将图表视图添加到布局中
this->setLayout(layout);                      // 将布局设置为当前widget的布局

2.12 添加数据点

//添加数据点
void graph::addDataPoint(float flowValue)
{
    //获取经过的时间(秒)
    double elapsedMinutes = startTimer.elapsed() / 1000.0;  // 计算从开始到现在经过的时间(秒)

    // 添加数据点
    series->append(elapsedMinutes, flowValue);  // 将当前时间和流量值作为新数据点添加到折线系列

    qDebug() << "添加数据点:" << flowValue << "mL/min";  // 输出调试信息,显示添加的流量数据

    //限制数据点数量(显示最近60秒数据)
    if(series->count() > 60)  // 如果数据点数量超过60个
    {
        series->removePoints(0, series->count() - 60);  // 移除最早的数据点,只保留最近60个点
    }

    // 自动调整X轴范围(显示最近60秒)
    double maxX = elapsedMinutes;  // 当前时间作为X轴最大值
    double minX = qMax(0.0, maxX - 60);  // X轴最小值为当前时间减去60秒,但不小于0
    axisX->setRange(minX, maxX);  // 更新X轴范围,实现图表的滚动效果

    // 自动调整Y轴范围
    double minY = 0;  // 初始化Y轴最小值
    double maxY = 0;  // 初始化Y轴最大值

    // 遍历所有可见数据点,找出最大值和最小值
    for(int i = 0; i < series->count(); i++)
    {
        QPointF point = series->at(i);  // 获取当前遍历的数据点
        if (point.x() >= minX) {       // 只处理当前X轴范围内(可见区域)的点
            if (point.y() < minY || minY == 0)  // 如果当前点的Y值小于已知最小值或最小值尚未设置
            {
                minY = point.y(); // 更新最小值
            }
            if (point.y() > maxY)  // 如果当前点的Y值大于已知最大值
            {
                maxY = point.y();  // 更新最大值
            }
        }
    }

    // 添加10%的边距,使图表显示更美观
    double margin = (maxY - minY) * 0.1;  // 计算边距为最大最小值差的10%
    if (margin == 0)  // 如果所有值相同(最大值等于最小值)
    {
        margin = maxY > 0 ? maxY * 0.1 : 10;  // 设置默认边距为最大值的10%或10
    }

    minY = qMax(0.0, minY - margin);  // 设置Y轴最小值,减去边距但不小于0
    maxY += margin;  // 设置Y轴最大值,加上边距

    axisY->setRange(minY, maxY);  // 更新Y轴范围,使所有数据点都能合适地显示
}

3、.h文件和.cpp文件

3.1 graph.h文件

#ifndef GRAPH_H
#define GRAPH_H

#include <QWidget>
#include <QtCharts>
#include <QPoint>
#include <QLineSeries>
#include <QValueAxis>
#include <QPoint>
#include <QChartView>

QT_CHARTS_USE_NAMESPACE

namespace Ui {
class graph;
}

class graph : public QWidget
{
    Q_OBJECT

public:
    explicit graph(QWidget *parent = nullptr);
    ~graph();

public slots:
    void addDataPoint(float flowValue);  // 添加数据点的槽函数

private:
    Ui::graph *ui;

    QChart *chart;               //图表对象
    QValueAxis *axisX;          //x轴
    QValueAxis *axisY;          //y轴
    QLineSeries *series;         //折线图
    QElapsedTimer  startTimer; // 记录图表开始时间

};
#endif // GRAPH_H

3.2 graph.cpp

#include "graph.h"
#include "ui_graph.h"

graph::graph(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::graph)
{
    ui->setupUi(this);

    //初始化
    chart = new QChart();           // 创建图表对象
    axisX = new QValueAxis();       // 创建X轴(时间轴)
    axisY = new QValueAxis();       // 创建Y轴(流量轴)
    series = new QLineSeries();     // 创建折线系列用于绘制数据


    // 配置X轴属性
    axisX->setTitleText("时间(s)");     // 设置X轴标题
    axisX->setLabelFormat("%d");        // 设置X轴标签格式为整数
    axisX->setRange(0,60);              // 设置X轴初始范围为0-60秒

    // 配置Y轴属性
    axisY->setTitleText("流量 (mL/min)"); // 设置Y轴标题
    axisY->setLabelFormat("%.1f");        // 设置Y轴标签格式为1位小数
    axisY->setRange(100, 600);           // 设置Y轴初始范围为100-600mL/min


    chart->addSeries(series);  // 将折线系列添加到图表

    // 将坐标轴添加到图表并设置位置
    chart->addAxis(axisX,Qt::AlignBottom); // X轴放置在底部
    chart->addAxis(axisY,Qt::AlignLeft);   // Y轴放置在左侧

    //将坐标轴添加到图表
    series->attachAxis(axisX);  // 关联X轴
    series->attachAxis(axisY);  // 关联Y轴

    //设置图表标题
    chart->setTitle("流量实时曲线");         // 设置图表标题
    chart->setAnimationOptions(QChart::NoAnimation); // 禁用动画提高性能
    chart->legend()->show();               // 显示图例

    //创建图表视图
    QChartView *chartView = new QChartView(chart);
    chartView->setRenderHint(QPainter::Antialiasing);        //抗锯齿

    //设置布局
    QVBoxLayout *layout = new QVBoxLayout(this);  // 创建垂直布局管理器
    layout->addWidget(chartView);                 // 将图表视图添加到布局中
    this->setLayout(layout);                      // 将布局设置为当前widget的布局


    //记录开始时间
    startTimer.start();

}

graph::~graph()
{
    delete ui;
}

//添加数据点
void graph::addDataPoint(float flowValue)
{
    //获取经过的时间(秒)
    double elapsedMinutes = startTimer.elapsed() / 1000.0;  // 计算从开始到现在经过的时间(秒)

    // 添加数据点
    series->append(elapsedMinutes, flowValue);  // 将当前时间和流量值作为新数据点添加到折线系列

    qDebug() << "添加数据点:" << flowValue << "mL/min";  // 输出调试信息,显示添加的流量数据

    //限制数据点数量(显示最近60秒数据)
    if(series->count() > 60)  // 如果数据点数量超过60个
    {
        series->removePoints(0, series->count() - 60);  // 移除最早的数据点,只保留最近60个点
    }

    // 自动调整X轴范围(显示最近60秒)
    double maxX = elapsedMinutes;  // 当前时间作为X轴最大值
    double minX = qMax(0.0, maxX - 60);  // X轴最小值为当前时间减去60秒,但不小于0
    axisX->setRange(minX, maxX);  // 更新X轴范围,实现图表的滚动效果

    // 自动调整Y轴范围
    double minY = 0;  // 初始化Y轴最小值
    double maxY = 0;  // 初始化Y轴最大值

    // 遍历所有可见数据点,找出最大值和最小值
    for(int i = 0; i < series->count(); i++)
    {
        QPointF point = series->at(i);  // 获取当前遍历的数据点
        if (point.x() >= minX) {       // 只处理当前X轴范围内(可见区域)的点
            if (point.y() < minY || minY == 0)  // 如果当前点的Y值小于已知最小值或最小值尚未设置
            {
                minY = point.y(); // 更新最小值
            }
            if (point.y() > maxY)  // 如果当前点的Y值大于已知最大值
            {
                maxY = point.y();  // 更新最大值
            }
        }
    }

    // 添加10%的边距,使图表显示更美观
    double margin = (maxY - minY) * 0.1;  // 计算边距为最大最小值差的10%
    if (margin == 0)  // 如果所有值相同(最大值等于最小值)
    {
        margin = maxY > 0 ? maxY * 0.1 : 10;  // 设置默认边距为最大值的10%或10
    }

    minY = qMax(0.0, minY - margin);  // 设置Y轴最小值,减去边距但不小于0
    maxY += margin;  // 设置Y轴最大值,加上边距

    axisY->setRange(minY, maxY);  // 更新Y轴范围,使所有数据点都能合适地显示
}

4、总结

以上就是QChart绘制折线图的整个过程了,浏览过程中,如若发现错误,欢迎大家指正,有问题的可以评论区留言或者私信。最后,如果大家觉得有所帮助的话,可以点个赞,谢谢大家!祝大家平安无疾,皆得所愿!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值