来来来,今天新学习到了一个好东西,就是图表的绘制,这玩意在一般的项目开发中的使用频率还是非常高滴,毕竟相对于数字来说,这个东西更能体现出数据的变化,主要是耐看啊!!!废话不多,我们直接上教程。
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
这样就能用啦!!!!
给只偷代码不认真看文档的同学当头一棒 啊哈哈哈哈哈哈哈哈哈哈哈哈哈!!!