一、前言
QChart 是一个图形库模块,它可以实现不同类型的序列和其他图表相关对象(如图例和轴)的图形表示。要在布局中简单地显示图表,可以使用QChartView 来代替QChart。此外,线条、样条、面积和散点序列可以通过使用QPolarChart类表示为极坐标图。
下面是一些简单数据的图标样式,区域图表、柱状图表、折线图表、饼状图表等。
而QPolarChart得到的极坐标图以圆形图形表示数据,其中数据的放置基于与图形中心(极点)的角度和距离。
但实际项目中上,我们用的最多的就是折线和柱状图表,做一些波形显示和能量统计。
使用该模块需要安装Qt环境的时候勾选Qt Charts,需要在pro文件中添加:Qt += charts
二、基本元素
我们的图表是二维的,在做图表之前,我们需要先了解几个图表的基本元素。
1、坐标轴
在坐标轴中X轴Y轴用来界定图表绘图区的线条,用作度量的参照框架,x 轴通常为水平轴,y 轴通常为垂直坐标轴。
2、坐标点
有了坐标轴,我们还需要坐标点。在y轴和x轴之间所取的一点,从y轴到该点的最短距离称作点的横坐标,从x轴到该点的最短距离称作点的纵坐标。
使用QPoint和QPoint存储坐标的值:
cpp
QPointF p(1.1, 2.2);
QPoint p(1, 2);
3、Series
当确定了坐标集合之后,这一系列的坐标称呼它为Series,也可以叫做集合,为不同的图表表现不同的样式,可以离散点、折线、曲线、区域等。Qt统一用了Series这个单词后缀来描述存储坐标信息和展现形式的类名,比如样条曲线QSplineSeries、折线QLineSeries、 散点QScatterSeries等等。
4、图例和标题
在图表中,图例是一个导航,用于快速选择该Series,标题就是该图表的名称。
三、基本图表和用法
3.1、QLineSeries
基于坐标点第一种Series,折线QLineSeries是设计用来存储坐标点信息显示折线的类,用起来很简单。
cpp
QChart *chart = new QChart();
QLineSeries *series = new QLineSeries(chart);
series->append(QPointF(1.1,2.2));
chart->addSeries(series);
3.2、QSplineSeries
基于坐标点第二种Series,样条曲线QSplineSeries继承于QLineSeries,当数据发生变化时,自动计算控制点,该算法计算点,绘制法向样条。
cpp
QChart *chart = new QChart();
QLineSeries *series = new QLineSeries(chart);
series->append(QPointF(1.1,2.2));
chart->addSeries(series);
3.3、QScatterSeries
基于坐标点第三种Series,散点QSplineSeries,它显示为一系列散落的点,当然还支持修改显示点的样式和颜色。
cpp
QChart *chart = new QChart();
QSplineSeries *series = new QSplineSeries(chart);
series->append(QPointF(1.1,2.2));
chart->addSeries(series);
3.4、QAreaSeries
区域QAreaSeries表现为两个一个区域的值,并用颜色填充,正常情况下,我们需要定义一条线QLineSeries/QSplineSeries表示这块区域的上线,x轴表示为下区域。如果不用x轴,也可以额外定义另一个线,表示下区域。
cpp
QLineSeries *upperSeries = new QLineSeries(chart);
QLineSeries *lowerSeries = new QLineSeries(chart);
QAreaSeries *area = new QAreaSeries(upperSeries, lowerSeries);
3.5、QBoxPlotSeries
盒须图QBoxPlotSeries用盒子和'须'表示一个集合的信息,并且每个点的x轴作为标签是唯一的,而y轴的数值是一个集合,包含五个信息,最大数、最小数、中位数、上半部份中位数、下半部分中位数,上半部份中位数和下半部分中位数中间的部分形成一个矩形填充颜色的区域。这些集合点的信息使用QBoxSet来存储和表示。
假如我有一些数字的集合,每一行前面代表时间,后面是一系列的数字,我们从中间挑出五个信息,形成图标。
cpp
# Acme Ltd share deviation in 2012
Jan 27.74 27.28 27.86 28.05 28.64 27.47 28.30 28.22 28.72 26.50 26.62 26.50 26.15 26.47 26.41 25.78 24.82 24.89 24.88 24.60 23.85
Feb 31.79 30.62 30.67 31.37 31.16 31.22 32.02 32.70 31.60 31.24 30.98 30.79 31.10 30.79 31.53 30.92 30.00 30.58 30.37 29.40 28.60
Mar 28.64 28.34 29.13 29.43 30.75 29.77 29.72 30.52 31.12 33.05 32.51 32.69 31.83 32.47 31.41 31.39 31.78 30.08 29.46 31.58 31.39 31.41
Apr 25.96 26.62 26.19 30.37 28.78 27.50 28.90 28.40 28.86 28.90 27.91 27.32 27.99 26.86 26.68 27.57 27.50 28.96 28.50
May 20.85 21.08 21.98 21.61 21.45 21.73 21.71 22.27 21.14 20.65 21.95 22.23 23.17 24.26 24.17 22.97 23.53 24.49 24.51 25.46 25.65
Jun 18.08 17.19 17.36 17.21 17.31 18.19 18.30 17.53 17.35 17.80 17.17 16.95 18.25 20.52 20.61 21.40 20.45 19.43 19.11 19.74
Jul 17.75 18.24 17.57 16.53 15.98 16.06 16.64 17.69 17.91 18.00 18.03 18.14 18.10 17.86 18.12 18.53 18.43 18.30 19.03 18.76 18.79 18.33
Aug 18.69 18.54 18.39 18.49 18.96 18.72 19.25 19.70 20.13 19.74 19.27 18.25 17.72 18.02 18.20 18.24 18.60 18.22 18.60 17.98 17.27 16.70 17.19
Sep 18.35 18.82 18.96 19.96 19.75 20.55 20.68 21.19 21.14 21.48 21.45 20.74 20.97 20.18 19.66 19.54 18.89 18.39 18.26 18.86
Oct 16.95 16.80 16.45 16.89 17.38 17.12 16.85 17.59 17.65 17.46 17.43 17.30 17.87 18.61 18.55 18.59 19.27 19.54 20.02 19.23 18.05 18.52 18.71
Now 19.36 19.29 18.22 18.74 19.05 19.13 18.67 18.19 17.94 18.04 17.49 17.53 17.64 18.00 18.21 18.19 18.30 18.11 18.17 17.76 17.80 17.52
Dec 19.95 20.19 20.15 20.42 20.39 20.65 20.39 19.86 19.48 19.70 19.94 19.82 20.25 20.21 19.63 19.55
cpp
//对每个盒子进行赋值
QBoxSet *set = new QBoxSet("....");
box->setValue(QBoxSet::LowerExtreme,10);
box->setValue(QBoxSet::UpperExtreme,100);
box->setValue(QBoxSet::Median,50);
box->setValue(QBoxSet::LowerQuartile,25);
box->setValue(QBoxSet::UpperQuartile,75);
//对盒子进行每个点的赋值
QBoxPlotSeries *acmeSeries = new QBoxPlotSeries();
acmeSeries->setName("Acme Ltd");
acmeSeries->append(set);
//添加到图表
QChart *chart = new QChart();
chart->addSeries(acmeSeries);
当有多条BoxPlotSeries添加到QChart的时候,会自动扩大x轴的标签,容纳下多个盒子。
3.6、QCandlestickSeries
创建烛台项目QCandlestickSeries的图形表示需要五个值:打开、高、低、关闭和时间戳,这些信息存储和表示在QCandlestickSet中,时间戳是唯一标签。
这东西就是设计用来给股票等交易场景用的,开盘价、最高点、最低点、关盘价和时间。
假如我们有这样一些数据:
cpp
# timestamp, open, high, low, close
1435708800000 126.90 126.94 125.99 126.60
1435795200000 126.69 126.69 126.69 126.69
1436140800000 124.85 126.23 124.85 126.00
1436227200000 125.89 126.15 123.77 125.69
1436313600000 124.64 124.64 122.54 122.54
1436400000000 123.85 124.06 119.22 120.07
1436486400000 121.94 123.85 121.21 123.28
1436745600000 125.03 125.76 124.32 125.66
1436832000000 126.04 126.37 125.04 125.61
1436918400000 125.72 127.15 125.58 126.82
1437004800000 127.74 128.57 127.35 128.51
1437091200000 129.08 129.62 128.31 129.62
1437350400000 130.97 132.97 130.70 132.07
1437436800000 132.85 132.92 130.32 130.75
1437523200000 121.99 125.50 121.99 125.22
1437609600000 126.20 127.09 125.06 125.16
1437696000000 125.32 125.74 123.90 124.50
1437955200000 123.09 123.61 122.12 122.77
1438041600000 123.38 123.91 122.55 123.38
1438128000000 123.15 123.50 122.27 122.99
1438214400000 122.32 122.57 121.71 122.37
1438300800000 122.60 122.64 120.91 121.30
我们把这些数字提取出来,保存到QCandlestickSet中,然后赋值给QCandlestickSeries,最终在QChart中表示。
cpp
//存储值的集合
QCandlestickSet *candlestickSet = new QCandlestickSet(timestamp);
candlestickSet->setOpen(open);
candlestickSet->setHigh(high);
candlestickSet->setLow(low);
candlestickSet->setClose(close);
//赋值
QCandlestickSeries *acmeSeries = new QCandlestickSeries();
acmeSeries->setName("Acme Ltd");
acmeSeries->setIncreasingColor(QColor(Qt::green));//收盘价高于开盘价显示上涨绿色
acmeSeries->setDecreasingColor(QColor(Qt::red));//收盘价低于开盘价显示下跌红色
acmeSeries->append(candlestickSet);
//显示
QChart *chart = new QChart();
chart->addSeries(acmeSeries);
chart->setTitle("Acme Ltd Historical Data (July 2015)");
chart->setAnimationOptions(QChart::SeriesAnimations);
3.7、QPieSeries
饼状图QPieSeries也是常见的图表,一般表现为两种形态,一种常规的饼状图,一种甜甜圈式的饼状图。
cpp
QPieSeries *series = new QPieSeries();
series->setHoleSize(0.35);//甜甜圈孔大小
series->append("Protein 4.2%", 4.2);
QPieSlice *slice = series->append("Fat 15.6%", 15.6);
slice->setExploded();
slice->setLabelVisible();
series->append("Other 23.8%", 23.8);
series->append("Carbs 56.4%", 56.4);
3.8、QStackedBarSeries/QHorizontalStackedBarSeries
栈柱状图,每个series水平叠放在一起,使用QBarSet存储数据。
cpp
QChart *chart = new QChart();
chart->setTitle("Bar chart");
QStackedBarSeries *series = new QStackedBarSeries(chart);
QBarSet *set = new QBarSet("Bar set " + "1");
*set <<1<<2<<3<<4<<5;
series->append(set);
chart->addSeris(series
chart->createDefaultAxes();
3.9、QBarSeries/QHorizontalBarSeries
常规柱状图,每个series根据水平并列在一起,使用QBarSet存储数据,参考上例。
3.10、QPercentBarSeries/QHorizontalPercentBarSeries
百分比柱状图,每个series根据百分比铺满,使用QBarSet存储数据,如果都是0则不渲染,参考上例。
可能Qt懒得修改了,按道理这几个柱状图单纯为了区分的样式和水平方向,理论上应该就是同一类,使用方法来设置枚举类型显示不同样式。
四:拓展
4.1、动画效果设置
图表的动画效果分别有网格的动画和series的动画,可以设置动画时间和动画播放时间曲线,这一般都很少用,顶多设置一下动画的持续时间。
4.2、动画效果重新播放
网格的动画效果在重新设置animationOptions或者设置主题的的时候会重新播放,但是series并不会有变化,只有在图表大小发生变化才会播放动画。
4.3、动态加载数据
cpp
((QLineSeries *)m_chartView->chart()->series().at(0))->append(x,y);
4.4、缩放图表
cpp
m_chartView->chart()->zoom(0.9);
m_chartView->chart()->zoom(1.1);
m_chartView->chart()->zoomReset();
4.5、滚轮缩放
鼠标滚轮缩放功能需要捕获鼠标事件,在事件处理滚轮动作,然后对图表进行缩放即可。
4.6、设置xy轴默认最大最小值
cpp
chart->axes(Qt::Vertical).first()->setMin(0);
chart->axes(Qt::Vertical).first()->setMax(100);
chart->axes(Qt::Horizontal).first()->setMin(0);
chart->axes(Qt::Horizontal).first()->setMax(100);