QChart双Y轴实时更新曲线图

QChart双Y轴,X轴设置时间轴

前言

工作上需要做一个双Y轴的折线图,除了看QT的相关类的文档,找到的资料不多,所以记录下来。

准备

首先,通过QT的帮助文档了解下QChart、QSplineSeries(或者其他的Series类)、QValueAxis等类的描述,翻译用的是有道的在线翻译,自己再稍微修改一下不通顺的地方。
QChart
The QChart class manages the graphical representation of the chart's series, legends, and axes.
QChart类管理图表中的线、图例和轴的图形表示。
QChart is a QGraphicsWidget that you can show in a QGraphicsScene. It manages the graphical representation of different types of series and other chart related objects like legend and axes. To simply show a chart in a layout, the convenience class QChartView can be used instead of QChart. In addition, line, spline, area, and scatter series can be presented as polar charts by using the QPolarChart class.
QChart是一个可以在QGraphicsScene中显示的QGraphicsWidget。它管理不同类型的系列和其他图表相关对象(如图例和轴)的图形表示。要简单地在布局中显示图表,可以使用便利类QChartView代替QChart。此外,直线、平滑曲线、面积和散射图可以通过QPolarChart类来表示为极坐标图。
QSplineSeries
The QSplineSeries class presents data as spline charts.
QSplineSeries类将数据表示为平滑曲线图。
A spline series stores the data points and the segment control points needed by QPainterPath to draw a spline. The control points are automatically calculated when the data changes. The algorithm computes the points so that the normal spline can be drawn.
一个spline series存储QPainterPath绘制平滑曲线所需的数据点和段控制点。当数据发生变化时,控制点会自动计算。该算法对点进行计算,以便绘制平滑曲线。
QValueAxis
QValueAxis class adds values to a chart's axes.
QValueAxis类将值添加到图表的轴中。
A value axis can be set up to show an axis line with tick marks, grid lines, and shades. The values on the axis are drawn at the positions of tick marks.
可以设置一个值轴来显示带有标记、网格线和阴影的轴线。在轴上的值是在标记的位置绘制的。
QDateTimeAxis
The QDateTimeAxis class adds dates and times to a chart's axis.
QDateTimeAxis类将日期和时间添加到图表的轴中。
QDateTimeAxis can be set up to show an axis line with tick marks, grid lines, and shades. The labels can be configured by setting an appropriate DateTime format. QDateTimeAxis works correctly with dates from 4714 BCE to 287396 CE. For other limitiations related to QDateTime, see QDateTime documentation.
可以设置QDateTimeAxis来显示带有标记标记、网格线和阴影的轴线。可以通过设置适当的DateTime格式来配置轴线上显示的值。QDateTimeAxis可以表示公元前4714年到公元287396年之间的时间。关于其他与QDateTime相关的信息,请参阅QDateTime文档。
Note : QDateTimeAxis is disabled on platforms that define qreal as float.
注意 :在将qreal定义为float的平台上禁用QDateTimeAxis。
关于设置双Y轴的比较重要的的函数是QChart的 addSeriesaddAxis这两个函数,前者是添加线到QChart中,后者是添加坐标轴到指定的位置。还有QSplineSeriesattachAxis函数。QT文档中的描述如下:
void QChart::addSeries(QAbstractSeries *series)
Adds the series series to the chart and takes ownership of it.
将series添加到chart中,并且chart获得series的所有权,即chart成为series的parent。
Note : A newly added series is not attached to any axes by default, not even those that might have been created for the chart using createDefaultAxes() before the series was added to the chart. If no axes are attached to the newly added series before the chart is shown, the series will get drawn as if it had axes with ranges that exactly fit the series to the plot area of the chart. This can be confusing if the same chart also displays other series that have properly attached axes, so always make sure you either call createDefaultAxes() after a series has been added or explicitly attach axes for the series.
注意 : 默认情况下,新添加的series不会附加到任何轴上,即使是那些在series添加到图表之前使用chart的createDefaultAxes()函数为图表创建的轴。如果在显示图表之前没有附加任何坐标轴到新添加的series上,那么这个数列就会被绘制出来,就好像它的坐标轴的范围恰好与这个series对应于图表的绘图区域一样。如果同一个图表还显示了其他附加了轴的series,那么这可能会绘制出令人困惑画面,所以一定要确保在添加了series之后再调用createDefaultAxes(),或者显式地为该series附加轴。
void QChart::addAxis(QAbstractAxis *axis, Qt::Alignment alignment)
Adds the axis axis to the chart aligned as specified by alignment. The chart takes the ownership of the axis.
将坐标轴添加到图表中的指定的位置(左边,下方,右边,上方)。这个chart获得坐标轴的所有权。
bool QAbstractSeries::attachAxis(QAbstractAxis *axis)
Attaches the axis specified by axis to the series.
将指定的坐标轴附加给series。
Returns true if the axis was attached successfully, false otherwise.
如果成功,返回true,否则,返回false
Note : If multiple axes of the same orientation are attached to the same series, they will have the same minimum and maximum values.
注意 :如果同一系列上有多个相同方向的轴,它们的最小值和最大值是相同的。

编码实现

接下来开始写代码,打开QT,我的是QT5.11,新建工程,在.pro文件里增加

QT+=charts

在源文件里添加QChart的头文件

#include <QtCharts>

#include <QtCharts/QSplineSeries>

在.cpp文件里增加命名空间

QT_CHARTS_USE_NAMESPACE       
//或者 using namespace QtCharts;

然后在QT设计师里往窗口添加一个Graphics View,然后提升为QChartView,


提升Graphics View

然后是编辑源文件,这里我就直接上代码了,代码里写有注释。
mainwindow.h文件

#ifndef MAINWINDOW_H

#define MAINWINDOW_H



#include <QMainWindow>

#include <QtCharts>

#include <QtCharts/QSplineSeries>

#include <QDateTime>

​

​

namespaceUi{

classMainWindow;

}

​

classMainWindow:publicQMainWindow

{

Q_OBJECT

​

public:

explicitMainWindow(QWidget*parent=0);

~MainWindow();

​

/*menbers**************************************************************************************/

//声明QChart的实例,QSplineSeries的实例

QChart*chart;

QSplineSeries*series1;

QSplineSeries*series2;

//声明timer

QTimer*timer;

​

/*funcions **************************************************************************************/

//声明划线的函数和初始化QChart的函数

voiddrawLine();

voidinitChart();

​

publicslots:

/*slot function**********************************************************************************/

//声明timer的槽函数

voidtimerDeal();

​

private:

Ui::MainWindow*ui;

};

​

#endif // MAINWINDOW_H

​mainwindow.cpp文件

#include "mainwindow.h"

#include "ui_mainwindow.h"

#include <math.h>

#include <QThread>

​

​

QT_CHARTS_USE_NAMESPACE

MainWindow::MainWindow(QWidget*parent) :

QMainWindow(parent),

ui(newUi::MainWindow)

{

ui->setupUi(this);

//初始化QChart

initChart();

​

//设置timer,槽连接到

timer=newQTimer();

timer->setInterval(400);

connect(timer,SIGNAL(timeout()),this,SLOT(timerDeal()));

timer->start();

}

​

MainWindow::~MainWindow()

{

deleteui;

}

​

//实现QChart的初始化函数

voidMainWindow::initChart()

{

//初始化QChart的实例

chart=newQChart();

​

//初始化两个QSplineSeries的实例

series1=newQSplineSeries();

series2=newQSplineSeries();

//设置两条曲线的名称

series1->setName("series1");

series2->setName("series2");

​

//把曲线添加到QChart的实例chart中

chart->addSeries(series1);

chart->addSeries(series2);

​

//声明并初始化X轴、两个Y轴

QDateTimeAxis*axisX=newQDateTimeAxis();

//    QValueAxis *axisX = new QValueAxis();

QValueAxis*axisY_1=newQValueAxis();

QValueAxis*axisY_2=newQValueAxis();

//设置坐标轴显示的范围

axisX->setMin(QDateTime::currentDateTime().addSecs(-60*1));

axisX->setMax(QDateTime::currentDateTime().addSecs(0));

axisY_1->setMin(0);

axisY_1->setMax(18);

axisY_2->setMin(0);

axisY_2->setMax(18);

​

//设置坐标轴上的格点

axisY_1->setTickCount(7);

axisY_2->setTickCount(11);

//设置坐标轴显示的名称

axisX->setTitleText("X轴");

axisY_1->setTitleText("axisY_1-series1");

axisY_2->setTitleText("axisY_2-series2");

//设置坐标轴的颜色,粗细,设置网格不显示

axisY_1->setLinePenColor(QColor(Qt::darkBlue));

axisY_1->setGridLineColor(QColor(Qt::darkBlue));

axisY_2->setLinePenColor(QColor(Qt::darkGreen));

axisY_2->setGridLineColor(QColor(Qt::darkGreen));

axisY_1->setGridLineVisible(false);

axisY_2->setGridLineVisible(false);

QPenpenY1(Qt::darkBlue,3,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin);

QPenpenY2(Qt::darkGreen,3,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin);

axisY_1->setLinePen(penY1);

axisY_2->setLinePen(penY2);

​

//把坐标轴添加到chart中,

//addAxis函数的第二个参数是设置坐标轴的位置,

//只有四个选项,下方:Qt::AlignBottom,左边:Qt::AlignLeft,右边:Qt::AlignRight,上方:Qt::AlignTop

chart->addAxis(axisX,Qt::AlignBottom);

chart->addAxis(axisY_1,Qt::AlignLeft);

chart->addAxis(axisY_2,Qt::AlignRight);

​

//把曲线关联到坐标轴

series1->attachAxis(axisX);

series1->attachAxis(axisY_1);

series2->attachAxis(axisX);

series2->attachAxis(axisY_2);

​

//把chart显示到窗口上

ui->graphicsView->setChart(chart);

​

}

​

//实现画线函数,动态更新

voidMainWindow::drawLine()

{

//每增加一个点改变X轴的范围,实现曲线的动态更新效果

QDateTimebjtime=QDateTime::currentDateTime();

qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));

chart->axisX()->setMin(QDateTime::currentDateTime().addSecs(-60*1));

chart->axisX()->setMax(QDateTime::currentDateTime().addSecs(0));

​

//当曲线上最早的点超出X轴的范围时,剔除最早的点,

if(series1->count()>119)

   {

series1->removePoints(0,series1->count()-119);

   }

if(series2->count()>119)

   {

series2->removePoints(0,series2->count()-119);

   }

​

intY1=qrand()%9;//随机生成0到9的随机数

intY2=9+qrand()%9;//随机生成9到18的随机数

//增加新的点到曲线末端

series1->append(bjtime.toMSecsSinceEpoch(),Y1);

series2->append(bjtime.toMSecsSinceEpoch(),Y2);

​

}

//实现timer的槽函数

voidMainWindow::timerDeal()

{

//定时画曲线

drawLine();

}

​最终效果,曲线和X轴的范围随着时间实时更新。


最终效果

总结

了解了以后,就觉得实现这个效果并不难,关键函数就那几个。虽说不难,也算是解决了一个问题,获得了成长。

声明

本文中的代码均为本人所写,本文亦是本人原创,转载请注明出处。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,701评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,649评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,037评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,994评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,018评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,796评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,481评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,370评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,868评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,014评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,153评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,832评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,494评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,039评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,437评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,131评论 2 356

推荐阅读更多精彩内容