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的 addSeries,addAxis这两个函数,前者是添加线到QChart中,后者是添加坐标轴到指定的位置。还有QSplineSeries的attachAxis函数。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
#include
在.cpp文件里增加命名空间
QT_CHARTS_USE_NAMESPACE
//或者 using namespace QtCharts;
然后在QT设计师里往窗口添加一个Graphics View,然后提升为QChartView,
然后是编辑源文件,这里我就直接上代码了,代码里写有注释。
mainwindow.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
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
#include
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轴的范围随着时间实时更新。
总结
了解了以后,就觉得实现这个效果并不难,关键函数就那几个。虽说不难,也算是解决了一个问题,获得了成长。
声明
本文中的代码均为本人所写,本文亦是本人原创,转载请注明出处。