Qt实现图表绘制

news2024/11/15 15:58:55

来来来,今天新学习到了一个好东西,就是图表的绘制,这玩意在一般的项目开发中的使用频率还是非常高滴,毕竟相对于数字来说,这个东西更能体现出数据的变化,主要是耐看啊!!!废话不多,我们直接上教程。

Qt实现图表绘制

1.绘制ui界面

创建项目我们就不多说了,说的太多了麻烦。

我是这样设计的,因为只是为了实践,所以没有考虑吧好看的因素。

一共是三个控件:1.lable2.button 3.Graphics View,老规矩,先将1,2水平布局,然后选中Widget对象后点击垂直布局

1.lable: 就是一个标签,用于显示我们的这个图表是干什么的,

2.button:转到槽,来控制保存图像

3.Graphics view:来显示我们的图表

2.编写代码

1.编写头文件

首先是头文件,毕竟我们要实现图表和绘制曲线和定时器随机数的生成。

1.这是.cpp的
#include "QChartView" // 包含QChartView类,用于显示图表
#include "QChart" // 包含QChart类,用于创建图表
#include "QValueAxis" // 包含QValueAxis类,用于创建值轴
#include "QSplineSeries" // 包含QSplineSeries类,用于创建曲线系列
#include "QTimer" // 包含QTimer头文件,用于定时器
#include <QRandomGenerator> // 用于生成随机数
#include "QMessageBox" // 包含QMessageBox类,用于显示消息框
2. 这是.h的
#include <QWidget>
#include <QChartView>
#include <QChart>
#include <QSplineSeries>
#include <QValueAxis>
#include <QTimer>

2.编写定时器

先在widget.h中定义我们的time

qreal time;               // 保存时间轴上的时间

然后在widget.cpp中初始化并连接我们的槽,(这里的槽是用来更新我们图像显示的,我们直接在定时器的初始化这里连接了)

// 初始化定时器并连接到 updateChart 槽
    QTimer *timer = new QTimer(this); // 创建定时器
    connect(timer, &QTimer::timeout, this, &Widget::updateChart); // 连接定时器超时信号到槽函数
    timer->start(1000); // 启动定时器,每隔1000毫秒(1秒)触发一次

3.编写图表和曲线的实现

1.初始化类成员变量

我们图表中有两个成员,一个是图表,一个是图表中的曲线

widget.h文件中声名一下:

QChart *chart;            // 保存图表对象
    QSplineSeries *splineSeries; // 保存曲线对象

widget.cpp中定义:

// 初始化类成员变量 chart 和 splineSeries
    chart = new QChart(); // 创建图表对象
    splineSeries = new QSplineSeries(); // 创建曲线系列对象

我们这里直接把初始点也定义出来吧

// 为 splineSeries 添加初始点
    splineSeries->append(0, 0); // 在曲线系列中添加点(0,0)

2.设置画笔

之前的文章中有写,其实这些线呢,是由QPen这个画笔函数搭配相应的函数来实现绘图的

QPen pen(QColor(0xff5566)); // 创建一个红色画笔
    splineSeries->setPen(pen); // 设置曲线系列的画笔

3.添加配置坐标轴并将曲线添加到图表中

我们创建好了图表,图表中要有XY轴,坐标轴要有相应的参数等,来看个图吧:(括号括起来的部分)

chart->addSeries(splineSeries); // 将曲线系列添加到图表中

    // 创建坐标轴
    QValueAxis *valueAxisX = new QValueAxis; // 创建X轴
    QValueAxis *valueAxisY = new QValueAxis; // 创建Y轴

    // 设置坐标轴范围
    valueAxisX->setRange(0, 5000); // 设置X轴范围为0到5000
    valueAxisY->setRange(0, 100); // 设置Y轴范围为0到100
    valueAxisX->setTitleText("时间/ms"); // 设置X轴标题
    valueAxisY->setTitleText("温度/°C"); // 设置Y轴标题

    valueAxisX->setLabelFormat("%d"); // 设置X轴标签格式为整数
    valueAxisY->setLabelFormat("%d"); // 设置Y轴标签格式为整数

    // 将坐标轴添加到图表并附加到曲线
    chart->addAxis(valueAxisX, Qt::AlignBottom); // 将X轴添加到图表底部
    chart->addAxis(valueAxisY, Qt::AlignLeft); // 将Y轴添加到图表左侧
    splineSeries->attachAxis(valueAxisX); // 将曲线系列附加到X轴
    splineSeries->attachAxis(valueAxisY); // 将曲线系列附加到Y轴

4.设置标题和图例显示

就是显示圈起来的那个玩意:

// 设置图表标题和图例
    chart->setTitle("温度与时间"); // 设置图表标题
    chart->legend()->setVisible(true); // 显示图例

5.显示图表

我们都弄好了之后我们要将我们设置好的图表显示到我们的UI文件当中。

// 将图表设置到图表视图中
    ui->chartview->setChart(chart); // 将图表对象设置到ui中的chartview控件

3.槽函数的编写

我们使用了两个槽函数,一个是图表中点的生成的槽函数,一个是保存按钮的槽函数,我们实现以下

1.图表中点的生成的槽函数

widget.h文件中声名一下这个函数

public slots:
    void updateChart();

widget.cpp中定义实现一下:

// 更新图表的槽函数
void Widget::updateChart()
{
    qreal randomTemp = QRandomGenerator::global()->bounded(0,100); // 生成0到100之间的随机数作为温度

    time += 1000; // 时间增加1000毫秒

    splineSeries->append(time,randomTemp); // 在曲线系列中添加新点

    QValueAxis *axisX = static_cast<QValueAxis*>(chart->axes(Qt::Horizontal).first()); // 获取X轴
    axisX->setRange(time - 5000, time); // 设置X轴范围,确保显示最近5秒的数据
}

2.保存按钮的槽函数:

这个直接在UI文件中转到槽就可以,他就会在widget.h文件中给你创建好

 

// 按钮点击槽函数
void Widget::on_pushButton_clicked()
{
    // 确保 X 轴显示所有数据
    if (!splineSeries->points().isEmpty()) {
        // 获取曲线中的最小和最大时间值
        qreal minX = splineSeries->points().first().x();
        qreal maxX = splineSeries->points().last().x();

        // 设置X轴范围覆盖所有数据点
        QValueAxis *axisX = static_cast<QValueAxis*>(chart->axes(Qt::Horizontal).first());
        axisX->setRange(minX, maxX);
    }

    // 获取 QChartView 的图像
    QPixmap pixmap = ui->chartview->grab(); // 捕获chartview的图像

    // 保存图像为 PNG 文件到当前项目目录
    QString fileName = "full_chart.png"; // 自定义保存文件名
    if (pixmap.save(fileName)) {
        // 成功保存后显示提示信息
        QMessageBox::information(this, "保存成功", "图表已保存为: " + fileName);
    } else {
        // 如果保存失败,提示错误信息
        QMessageBox::warning(this, "保存失败", "无法保存图表,请检查路径或文件权限。");
    }
}

4.扩展:

 然后·····就没有然后啦,就这样,如果想在添加两个按钮实现点击开始按钮开始生成,点击停止按钮就停止生成,这个也简单。定义两个按钮,之后转到槽,将定时器的start()函数设置到这里,就可以控制定时器的开关从而控制图像的生成了

5.总代码

widget.cpp

#include "widget.h" // 包含Widget类的声明
#include "ui_widget.h" // 包含由UI设计器生成的Widget的UI部分
#include "QChartView" // 包含QChartView类,用于显示图表
#include "QChart" // 包含QChart类,用于创建图表
#include "QValueAxis" // 包含QValueAxis类,用于创建值轴
#include "QSplineSeries" // 包含QSplineSeries类,用于创建曲线系列
#include "QTimer" // 包含QTimer头文件,用于定时器
#include <QRandomGenerator> // 用于生成随机数
#include "QMessageBox" // 包含QMessageBox类,用于显示消息框

// Widget类的构造函数
Widget::Widget(QWidget *parent)
    : QWidget(parent) // 调用基类的构造函数
    , ui(new Ui::Widget) // 初始化UI指针
    , time(0) // 初始化时间变量
{
    ui->setupUi(this); // 初始化UI

    // 初始化定时器并连接到 updateChart 槽
    QTimer *timer = new QTimer(this); // 创建定时器
    connect(timer, &QTimer::timeout, this, &Widget::updateChart); // 连接定时器超时信号到槽函数
    timer->start(1000); // 启动定时器,每隔1000毫秒(1秒)触发一次

    // 初始化类成员变量 chart 和 splineSeries
    chart = new QChart(); // 创建图表对象
    splineSeries = new QSplineSeries(); // 创建曲线系列对象

    // 为 splineSeries 添加初始点
    splineSeries->append(0, 0); // 在曲线系列中添加点(0,0)

    QPen pen(QColor(0xff5566)); // 创建一个红色画笔
    splineSeries->setPen(pen); // 设置曲线系列的画笔

    // 将曲线添加到图表
    chart->addSeries(splineSeries); // 将曲线系列添加到图表中

    // 创建坐标轴
    QValueAxis *valueAxisX = new QValueAxis; // 创建X轴
    QValueAxis *valueAxisY = new QValueAxis; // 创建Y轴

    // 设置坐标轴范围
    valueAxisX->setRange(0, 5000); // 设置X轴范围为0到5000
    valueAxisY->setRange(0, 100); // 设置Y轴范围为0到100
    valueAxisX->setTitleText("时间/ms"); // 设置X轴标题
    valueAxisY->setTitleText("温度/°C"); // 设置Y轴标题

    valueAxisX->setLabelFormat("%d"); // 设置X轴标签格式为整数
    valueAxisY->setLabelFormat("%d"); // 设置Y轴标签格式为整数

    // 将坐标轴添加到图表并附加到曲线
    chart->addAxis(valueAxisX, Qt::AlignBottom); // 将X轴添加到图表底部
    chart->addAxis(valueAxisY, Qt::AlignLeft); // 将Y轴添加到图表左侧
    splineSeries->attachAxis(valueAxisX); // 将曲线系列附加到X轴
    splineSeries->attachAxis(valueAxisY); // 将曲线系列附加到Y轴

    // 设置图表标题和图例
    chart->setTitle("温度与时间"); // 设置图表标题
    chart->legend()->setVisible(true); // 显示图例

    // 将图表设置到图表视图中
    ui->chartview->setChart(chart); // 将图表对象设置到ui中的chartview控件
}

// Widget类的析构函数
Widget::~Widget()
{
    delete ui; // 清理UI指针
}

// 更新图表的槽函数
void Widget::updateChart()
{
    qreal randomTemp = QRandomGenerator::global()->bounded(0,100); // 生成0到100之间的随机数作为温度

    time += 1000; // 时间增加1000毫秒

    splineSeries->append(time,randomTemp); // 在曲线系列中添加新点

    QValueAxis *axisX = static_cast<QValueAxis*>(chart->axes(Qt::Horizontal).first()); // 获取X轴
    axisX->setRange(time - 5000, time); // 设置X轴范围,确保显示最近5秒的数据
}

// 按钮点击槽函数
void Widget::on_pushButton_clicked()
{
    // 确保 X 轴显示所有数据
    if (!splineSeries->points().isEmpty()) {
        // 获取曲线中的最小和最大时间值
        qreal minX = splineSeries->points().first().x();
        qreal maxX = splineSeries->points().last().x();

        // 设置X轴范围覆盖所有数据点
        QValueAxis *axisX = static_cast<QValueAxis*>(chart->axes(Qt::Horizontal).first());
        axisX->setRange(minX, maxX);
    }

    // 获取 QChartView 的图像
    QPixmap pixmap = ui->chartview->grab(); // 捕获chartview的图像

    // 保存图像为 PNG 文件到当前项目目录
    QString fileName = "full_chart.png"; // 自定义保存文件名
    if (pixmap.save(fileName)) {
        // 成功保存后显示提示信息
        QMessageBox::information(this, "保存成功", "图表已保存为: " + fileName);
    } else {
        // 如果保存失败,提示错误信息
        QMessageBox::warning(this, "保存失败", "无法保存图表,请检查路径或文件权限。");
    }
}

widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QChartView>
#include <QChart>
#include <QSplineSeries>
#include <QValueAxis>
#include <QTimer>
QT_CHARTS_USE_NAMESPACE

    QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

public slots:
    void updateChart();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    QChart *chart;            // 保存图表对象
    QSplineSeries *splineSeries; // 保存曲线对象
    qreal time;               // 保存时间轴上的时间
};

#endif // WIDGET_H

UI文件截图:

槽!!!注意这里有一个重点!!!想起来了

我们使用的控件是QGraphicsView,因为Qt自带的控件中没有我们的QChartView,但是QChartView是QGraphics的子类,所以我们右键QGraphicsView,将他提升为QChartView

这样就能用啦!!!!

 给只偷代码不认真看文档的同学当头一棒 啊哈哈哈哈哈哈哈哈哈哈哈哈哈!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2107001.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

9月跨境营销热点日历!出海选品指南

9月1日 澳大利亚父亲节 澳大利亚父亲节是一个特殊的日子&#xff0c;人们用来表达对父亲的感激之情。 礼物用品&#xff1a;手表盒、雪茄盒、红酒架、腰带等。除了前面举例的几款&#xff0c;还能从哪里获取选品的灵感呢&#xff1f;店雷达给大家提供一些实操的选品思路&…

p38激酶在癌症研究中的进展

前 言&#xff1a; p38是丝裂原活化蛋白激酶MAPK家族的重要成员。p38的激活需要在Thr180、Tyr182位点发生磷酸化&#xff0c;在细胞增殖、代谢、凋亡等方面发挥重要作用&#xff0c;与多种肿瘤发展相关。 MAPK&#xff08;丝裂原活化蛋白激酶&#xff09;通路参与调控与癌症发…

【Linux】常见指令及权限相关知识详细梳理

1.Linux基本指令 1. ls指令 语法&#xff1a; ls [选项][目录或文件] 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。 对于文件&#xff0c;将列出文件名以及其他信息。 常用选项&#xff1a; -a 列出目录下的所有文件&#xf…

ARM V2微架构

简介 今年V3/N3已经发布&#xff0c;但考虑到没有公布太多的细节&#xff0c;我依据手册在“ARM发布新一代高性能处理器”一文中对微架构有阐述&#xff0c;本文主要简单分析ARM V2的一些微架构内容。 IFU 1、每个cycle预测两个分支&#xff0c;这个特性在服务器系列中是N2/V…

vue数字滚动插件vue-countTo

文章目录 1. vue-countTo2. 使用2.1 安装2.2 页面使用 3. 参数4. 方法 1. vue-countTo 这是一个 vue 组件&#xff0c;它会在指定的时间内计数到目标数字 vue-countTo 是一个无依赖的轻量级 vue 组件&#xff0c;可以自行覆盖 easingFn&#xff0c;可以设置 startVal 和 endVal…

【无标题】如何申报团体标准,需要具备哪些条件

在当今快速发展的社会中&#xff0c;团体标准的重要性日益凸显。它不仅能够推动行业的进步与创新&#xff0c;还能提升企业的竞争力。那么&#xff0c;如何申报团体标准呢&#xff1f;又需要具备哪些条件呢&#xff1f;让我们一同来深入了解。 申报团体标准的流程和所需条件可能…

如何让工作汇报不再平庸?

在职场中&#xff0c;工作汇报是每位员工不可或缺的一部分&#xff0c;它不仅是展示个人成果与能力的窗口&#xff0c;也是促进团队沟通与协作的重要桥梁。 1、明确目标与听众 不同的听众有不同的关注点和期望&#xff0c;了解他们的背景和需求&#xff0c;能够让你在汇报中有…

创客匠人9月活动|预告

-----------------------------------------创客匠人&#xff1a;让知识变现不走弯路-----------------------------------------

7月刷题笔记

刷题笔记—7月 1512.好数对的数目(哈希) class Solution { public:int numIdenticalPairs(vector<int>& nums) {int cnt 0;unordered_map<int, int> hash;//nums[i]---个数for(int i 0; i < nums.size(); i) {cnt hash[nums[i]];hash[nums[i]];}return…

【鸿蒙】HarmonyOS NEXT星河入门到实战1-开发环境准备

目录 一、达成目标 二、鸿蒙开发环境准备 2.1 开发者工作下载 2.2 解压安装 2.3 运行配置安装node.js和SDK 2.4 开始创建第一个项目 2.5 预览 2.5.1 预览遇到的问题&#xff08;报错&#xff09; 2.5.2 修改内容查看预览 三、备用下载地址&#xff08;如果下载是4.X版…

Android平台RTSP|RTMP播放器(SmartPlayer)集成必读

技术背景 好多开发者拿到大牛直播SDK的Android平台RTSP、RTMP播放模块&#xff0c;基本上不看说明&#xff0c;测试后&#xff0c;就直接集成到自己系统了。不得不说&#xff0c;我们的模块虽然接口很多&#xff0c;功能支持全面&#xff0c;但是上层的demo设计逻辑确实简单&a…

【PyTorch][chapter 29][李宏毅深度学习][transformer-3] 使用PyTorch构建 Transformer

前言: 参考&#xff1a; https://www.datacamp.com/tutorial/building-a-transformer-with-py-torch, 使用PyTorch 构建Transformer 主要分为下面几步, 定义基本构建块——多头注意力、位置前馈网络、位置编码构建编码器块构建解码器块结合编码器和解码器层来创建完整的Transf…

零基础能做Oracle数据库之间的迁移吗?

没有技术背景的人&#xff0c;如何把企业的 Oracle 数据库平稳、无缝、无停机地迁移到另一个 Oracle 数据库&#xff1f; 可能会有人觉得这个话题很无聊&#xff0c;毕竟是承载企业核心数据的数据库&#xff0c;不会真有人拿企业的命脉开玩笑吧&#xff1f;但是事实上&#xf…

行空板上YOLO和Mediapipe视频物体检测的测试

Introduction 经过前面三篇教程帖子&#xff08;yolov8n在行空板上的运行&#xff08;中文&#xff09;&#xff0c;yolov10n在行空板上的运行&#xff08;中文&#xff09;&#xff0c;Mediapipe在行空板上的运行&#xff08;中文&#xff09;&#xff09;的介绍&#xff0c;…

张飞硬件10-TVS管篇笔记

TVS管的原理 TVS或称瞬变电压抑制二极管&#xff0c;是在二极管工艺基础上发展起来的新产品&#xff0c;其电路符号和普通稳压管相同&#xff0c;外形也与普通二极管无异。当TVS管两端经受瞬间的高能量冲击时&#xff0c;它能以极高的速度将其阻抗骤然降低&#xff0c;同时吸收…

多账套场景下Oracle EBS 导入日记账时需要进行平衡段的校验

处理要进行COA的校验之外&#xff0c;还要进行账套配置这个地方&#xff0c;平衡段的校验,相关参参照关系见如下sql(Doc ID 943582.1)&#xff1a; -- 1. SELECT *FROM gl_ledgersWHERE ledger_id &ledger_id;--2. SELECT *FROM gl_ledger_configurationsWHERE configurat…

JVM类的加载和类的加载器

JVM类的加载和类的加载器 一.类的加载过程 类的加载指的是将类的.class文件中的二进制数据读入到内存中&#xff0c;将其放在运行时数据区的方法区内&#xff0c;然后在堆区创建一个java.lang.Class对象&#xff0c;用来封装类在方法区内的数据结构。类的加载的最终产品是位于…

应用方案丨D02低功耗霍尔开关

1、概述 D02 是一款低功耗全极霍尔开关&#xff0c;用于检测施加的磁通量密度&#xff0c;并提供一个数字输出&#xff0c;该输出指示所感测磁通量幅度的当前状态。这些应用的一个例子是翻盖手机中的 ON/OFF 开关。微功耗设计特别适合电池供电系统&#xff0c;如手机或笔记本电…

附送试听地址!OpenAI ChatGPT被曝将新增8种语音!英特尔酷睿Ultra 200V正式发布|AI日报

文章推荐 如人类交流一样丝滑&#xff01;讯飞星火版「Her」正式上线&#xff01;成立仅16月的无问芯穹完成近5亿元A轮融资&#xff5c;AI日报 8款国内外免费AI生成视频工具对比实测&#xff01;我们真的可以做到“一人搞定一部影视作品“吗&#xff1f; 今日热点 Sam Altm…

图像指定领域随机变换

资料生成和模型训练 图像指定领域随机变换 在计算机视觉领域中&#xff0c;除了瑕疵、灯光和场景随机变换外&#xff0c;还有许多其他常见的随机变换方法&#xff0c;可以帮助增强数据集的多样性和模型的泛化能力。以下是一些常见的随机变换&#xff1a; 1.随机剪切&#xf…