持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情
之前由于没有绘图需求,一直没有关注QChart这个类,最近有个朋友向我求助,如何将STM32的四个数据实时绘制到图中,于是将朋友的需求转换成代码并记录下来。
废话不多说,先看一下代码最终的效果,本代码以两条曲线为例,如果需要添加更多曲线,直接在源码中修改即可。
界面最上面的按钮中"clear window"作用是清除界面中已经绘制的曲线,并且停止曲线绘制,"data generate"作用是生成数据并开始实时绘制曲线。由于只包含两条曲线,因此曲线对象的名称也只有两个,分别是"V/T Curve"和"I/TCurve",这个名字随便取,只要符合自己数据表示的意义即可,此处作为demo,名字也是随意取的。
绘图过程中设置了计时器,从而实现周期性绘图,每隔1秒绘制一次数据,两个数据同时绘制。
下面直接上代码 首先UI文件设置如下
然后在项目文件中添加如下一行代码
QT += charts
// widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTimer>
#include <QChartView>
#include <QValueAxis>
#include <QLineSeries>
// 加入命名空间
QT_CHARTS_USE_NAMESPACE
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
Ui::Widget *ui;
private:
QTimer* myTimer;
//图表对象
QChart* myChart;
QChart* myChart1;
// 横纵坐标轴对象
QValueAxis *myAxisX, *myAxisY;
// 曲线图对象
QLineSeries* myLineSeries;
QLineSeries* myLineSeries1;
// 横纵坐标最大显示范围
const int AXIS_MAX_X = 10, AXIS_MAX_Y = 10;
// 用来记录数据点数
int pointCount = 0;
private slots:
void slotBtnClear();
void slotBtnStartAndStop();
void slotTimeout();
};
#endif // WIDGET_H
//widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
myTimer = new QTimer(this);
myTimer->setSingleShot(false);
QObject::connect(myTimer, SIGNAL(timeout()), this, SLOT(slotTimeout()));
QObject::connect(ui->btnClear, SIGNAL(clicked(bool)), this, SLOT(slotBtnClear()));
QObject::connect(ui->btnStartAndStop, SIGNAL(clicked(bool)), this, SLOT(slotBtnStartAndStop()));
// 创建横纵坐标轴并设置显示范围
myAxisX = new QValueAxis();
myAxisY = new QValueAxis();
myAxisX->setTitleText("V");
myAxisY->setTitleText("T");
myAxisX->setMin(0);
myAxisY->setMax(0);
myAxisX->setMax(AXIS_MAX_X);
myAxisY->setMax(AXIS_MAX_Y);
// 创建曲线对象
myLineSeries = new QLineSeries();
myLineSeries1 = new QLineSeries();
// 将数据设置可见
myLineSeries->setPointsVisible(true);
myLineSeries1->setPointsVisible(true);
myLineSeries->setName("V/T-Curve");
myLineSeries1->setName("I/T-Curve");
// 创建图表对象
myChart = new QChart();
// 坐标轴添加到图表中
myChart->addAxis(myAxisX, Qt::AlignLeft);
myChart->addAxis(myAxisY, Qt::AlignBottom);
// 将曲线添加到图表
myChart->addSeries(myLineSeries);
myChart->addSeries(myLineSeries1);
// 设置权限过渡动画
myChart->setAnimationOptions(QChart::SeriesAnimations);
// 曲线对象关联坐标轴,该步骤必须置于曲线添加到图标之后
myLineSeries->attachAxis(myAxisX);
myLineSeries->attachAxis(myAxisY);
myLineSeries1->attachAxis(myAxisX);
myLineSeries1->attachAxis(myAxisY);
// 将图表对象设置到graphicsView上进行显示
ui->graphicsView->setChart(myChart);
// 为了使曲线看起来更加平滑设置渲染:抗锯齿
ui->graphicsView->setRenderHint(QPainter::RenderHint::Antialiasing);
}
Widget::~Widget()
{
delete ui;
}
// 清除chart中所有的坐标
void Widget::slotBtnClear()
{
myLineSeries->clear();
myLineSeries1->clear();
myChart->axisX()->setMin(0);
myChart->axisX()->setMax(AXIS_MAX_X);
pointCount = 0;
}
// 设置定时器
void Widget::slotBtnStartAndStop()
{
if(myTimer->isActive())
{
myTimer->stop();
ui->btnStartAndStop->setText("timer start");
}else
{
pointCount = 0;
myTimer->start(1000);
ui->btnStartAndStop->setText("timer stop");
}
}
// 设置定时器触发函数,主要是更新数据
void Widget::slotTimeout()
{
if(pointCount > AXIS_MAX_X)
{
myLineSeries->remove(0);
myLineSeries1->remove(0);
myChart->axisX()->setMin(pointCount - AXIS_MAX_X);
// 更新X轴范围,此处设定一直保持0-10范围,超出后归零
myChart->axisX()->setMax(pointCount);
}
// 第一条曲线显示数据
myLineSeries->append(QPointF(pointCount, (rand() % AXIS_MAX_Y)));
// 第二条曲线显示数据
myLineSeries1->append(QPointF(pointCount, (rand() % AXIS_MAX_Y)+2));
pointCount++;
if(pointCount > 11)
{
myLineSeries->clear();
myLineSeries1->clear();
myChart->axisX()->setMin(0);
myChart->axisX()->setMax(AXIS_MAX_X);
pointCount = 0;
}
}
此处main.cpp就不放上去了,新建工程时直接用默认的main.cpp即可,没有改动。需要整个工程目录的可以在评论中联系我,直接邮箱发送给你即可,一起学习以期提高。