Qt开发总结(19)——Qt Charts

上两篇记录了Qt的基本绘图QPainter和Graphics View绘图架构。还是在Qt4的时代,我用这个QPainter写了一个Plot类,实现了简单的二维曲线动态绘制。后来,我接触到了qwt,一款强大的第三方库Qt图表库,再后来,Qt5官方把Qt Charts和Data Visualization开放在了社区版里,使得我们可以轻松采用这两款官方插件实现二维和三维图表绘制了。接下来的几篇将总结这几个图表插件,本篇是Qt Charts。

概述

Qt Charts是Qt提供的图表模块,在Qt5.7之前只有商业版才有,但是从Qt5.7之后,社区版本也包含了Qt Charts。Qt Charts可以很方便的绘制常见的折线图、柱状图、饼图等图表。它基于Qt的Graphics View架构,核心组件是QChartView和QChart。其中QChartView正是继承于QGraphicsView类,因此它也可以作为Graphics View中的视图组件。另一个QChart则由QGraphicsWidget继承而来,继续向上追溯,发现他们都继承于QGraphicsItem,所以QChart是图形项。

要使用Qt Charts,需要在pro文件中增加Qt += charts,在代码中需要添加QtCharts头文件和命名空间。

#include <QtCharts>

using namespace QtCharts;

或用宏定义:

Qt_CHARTS_USE_NAMESPACE

在使用时可以设置不同的主题,修改颜色和属性,或是动态显示曲线。使用的基本流程如下:

  

        //在mainwindow或是widget上新建QChartView
	QChartView *chartView = new QChartView(this);	
	chartView->resize(400,300);
	
	//创建QChart,进行简单设置
	QChart *chart = new QChart();	
	chart->legend()->hide();	//隐藏图例
	chart->setTitle("simple");	//设置标题
	chart->createDefaultAxes();	//创建默认坐标轴
	chartView->setChart(chart);	//chart添加到chartView

	//创建曲线
	QLineSeries *series = new QLineSeries();					
	series->append(0, 6);
	series->append(2, 4);
	series->append(3, 8);
	series->append(7, 4);
	series->append(10, 5);
	*series << QPointF(11, 1) << QPointF(13, 3) << QPointF(17, 6) 
			<< QPointF(18, 3) << QPointF(20, 2);
	
	//把曲线添加到图表
	chart->addSeries(series);

 

图表类别

Qt Charts模块提供以下几类图表类型,每个图表都通过QAbstractSeries来实现具体形式。具体来说就是把series类的对象添加到QChart or ChartView对象中。当然,你可以在一个图表中混合添加多种曲线。

  QLineSeries* series = new QLineSeries();
  series->add(0, 6);
  series->add(2, 4);
  ...
  chartView->chart()->addSeries(series);
  chartView->chart()->createDefaultAxes();

 

 

1.直线和曲线

用点连接起来的直线,曲线通过QPainterPath连接。直线实现的时候通过QLineSeries类,曲线通过QSplineSeries实现。

2.面积和散点图

面积图表把数据显示为用两条线围成的一个面积区域,散点图则把数据显示为一些列点的集合。通过QAreaSeries类实现面积图,默认情况下,X轴被认为是一个边界,另一个边界用QLineSeries实现。通过QScatterSeries类实现散点图。

 

3.柱状图

柱状图把数据显示为垂直或水平的柱状形状。通过QBarSet类实现柱状图中的柱形,QAbstractBarSeries类是所有柱形形状类的基类,QBarSeries用来表示其中垂直柱形的数据,QHorizontalBarSeries用来表示水平柱形的数据。QStackedBarSeries用来表示垂直的堆叠柱状图。QHorizontalStackedBarSeries则用来表示水平的堆叠状图。QPercentBarSeries用来表示垂直的百分比柱状图,而QHorizontalPercentBarSeries用来表示水平的百分比柱状图。

 

 

 

4.饼图

饼图是把数据显示为饼状,且分割为若干片。通过QPieSeries类实现。饼图可以设置中间为空,孔洞大小可以被设置为0.0-1.0。

 

5.火柴盒图和烛台图

如果你玩股票,那么你应该很熟悉烛台图,如果你不知道它,请自行百度。大概就是柱形图和曲线图的结合,通过QBoxPlotSeries和QBoxSet类来实现。

6.极坐标图

用圆形极坐标系表征数据,数据用距离和角度表示。QPolarChart是QChart的一个子类,主持直线,曲线,面积和散点图。同时还支持所有的坐标轴类型。

坐标轴(Axes)

Qt Charts支持以下坐标轴类型:

  • 数值坐标轴
  • 分组数值坐标轴
  • 类别坐标轴
  • 日期时间坐标轴
  • 对数数值坐标轴

坐标轴可以被设置为刻度线,网格和投影,数据被按照刻度绘制在特定位置。所有的坐标轴类都是从QAbstractAxis基类继承而来,QValueAxis类实现了数值坐标轴,可以作为数值型数据的坐标轴;QCategoryAxis类实现了分组数值坐标轴,可以为数值范围设置文字标签;QBarCategoryAxis类类似于QCategoryAxis,实现了类别坐标轴,用字符串为作为坐标轴的刻度,用于图表的非数值坐标轴;QDateTimeAxis类实现了日期时间坐标轴,作为日期时间数据的坐标轴;QLogValueAxis类实现了对数数值坐标轴,所谓数值数据的对数坐标轴,可以设置对数的基。

图表可以定义多个坐标轴,坐标轴可以被放置于图表的上、左、右、下等区域。

图例(Legend)

图例是对图表上的显示序列的示例说明。图例的对象本身不可以被创建和删除,但是可以通过QChart控制它。当数据序列发生改变时,QChart or ChartView会自动更新图例。

图例可以被放置到图表的上、左、右、下位置,默认的,图例附着在图表视图上,也可以把它分离出来,独立成一个窗体,从而实现自由放置。

可以隐藏单个条目或者整个图例标签。图例的标签用QLegendMarker基类和其派生类管理,这些派生类主要有:QAreaLegendMarker, QBarLegendMarker, QBoxPlotLegendMarker, QCandlestickLegendMarker, and QXYLegendMarker.

交互

这里罗列一些常见的交互形式。

1.动态绘制数据

可以动态向图表添加数据,并使得图表自动滚动以显示新的数据。这就是常说的动态曲线。实际上只需要定时器的响应函数中增加坐标轴的变化即可:

Chart::Chart(QGraphicsItem *parent, Qt::WindowFlags wFlags) :
	QChart(QChart::ChartTypeCartesian, parent, wFlags),
	m_series(0),
	m_axis(new QValueAxis),
	m_x(0),
	m_y(0)
{
	qsrand((uint)QTime::currentTime().msec());

	QObject::connect(&m_timer, &QTimer::timeout, this, &Chart::handleTimeout);
	m_timer.setInterval(200);

	m_series = new QSplineSeries();
	addSeries(m_series);

	createDefaultAxes();
	setAxisX(m_axis, m_series);
	axisX()->setRange(0, 20);	//初始化X轴区域
	axisY()->setRange(-2.5, 2.5);//初始化y轴区域

	m_timer.start();
}

Chart::~Chart()
{

}

void Chart::handleTimeout()
{
	m_y = sin(m_x);
	m_series->append(m_x, m_y);
	if (m_x>20)
	{
		axisX()->setRange(0, m_x + 5);	//坐标轴自适应
	}	
	if (m_x == 100)
		m_timer.stop();
	m_x++;
}

 

2.下钻数据

对于柱状图或者饼图,当用户选择了表格中的某个项目时,一个更加详细的视图会显示出来,这个过程叫做下钻数据。

    DrilldownChart *chart = new DrilldownChart();
    chart->setTheme(QChart::ChartThemeLight);
    chart->setAnimationOptions(QChart::AllAnimations);
    chart->legend()->setVisible(true);
    chart->legend()->setAlignment(Qt::AlignRight);

    QPieSeries *yearSeries = new QPieSeries(&window);
    yearSeries->setName("Sales by year - All");

    const QStringList months = {
        "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    };
    const QStringList names = {
        "Jane", "John", "Axel", "Mary", "Susan", "Bob"
    };

    for (const QString &name : names) {
        QPieSeries *series = new QPieSeries(&window);
        series->setName("Sales by month - " + name);

        for (const QString &month : months)
            *series << new DrilldownSlice(qrand() % 1000, month, yearSeries);

        QObject::connect(series, &QPieSeries::clicked, chart, &DrilldownChart::handleSliceClicked);

        *yearSeries << new DrilldownSlice(series->sum(), name, series);
    }

    QObject::connect(yearSeries, &QPieSeries::clicked, chart, &DrilldownChart::handleSliceClicked);

    chart->changeSeries(yearSeries);

 

在handleSliceClicked响应中再次调用changeSeries函数。

3.缩放和滚动

用户可以使用键盘进行缩放或滚动操作。QRubberBand可以被用来选择要被缩放的区域。

bool Chart::gestureEvent(QGestureEvent *event)
{
    if (QGesture *gesture = event->gesture(Qt::PanGesture)) {
        QPanGesture *pan = static_cast<QPanGesture *>(gesture);
        QChart::scroll(-(pan->delta().x()), pan->delta().y());
    }

    if (QGesture *gesture = event->gesture(Qt::PinchGesture)) {
        QPinchGesture *pinch = static_cast<QPinchGesture *>(gesture);
        if (pinch->changeFlags() & QPinchGesture::ScaleFactorChanged)
            QChart::zoom(pinch->scaleFactor());
    }

    return true;
}

 

4.鼠标响应

可以设计信号和槽函数来实现鼠标点击或者浮动在图表上的操作。这使得你可以为图表增加元素,比如标注:

主题

Qt Charts提供了丰富的主题,集合了特定的颜色、画笔、画刷以及字体,另外还有坐标轴、标题和图例,让图表以更加美化的方式显示出来。

 

  • Light theme, which is the default theme
  • Cerulean blue theme
  • Dark theme
  • Sand brown theme
  • Natural color system (NCS) blue theme
  • High contrast theme
  • Icy blue theme
  • Qt theme

这些主题也可以被在源码中定制修改。另外,要注意,更换主题后,之前的修改将会被覆盖重写,所以还是建议参照源码中的例子,自己编写代码控制主题。

例子

这里放两个例子,一个是上面这个主题的例子,它里面同时也包含了各种图表绘制方法:

chartthemes,另外一个是自定义图标例子:customchart  https://download.csdn.net/download/bjtuwayne/12033059

发布了76 篇原创文章 · 获赞 63 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/bjtuwayne/article/details/103642828