从Qt 5.7开始,在开源版Qt中可以使用Qt Charts模块来创建几乎所有常见的图表类型,包括折线图、曲线图、面积图、散点图、柱形图、饼状图、盒须图等等,而且还提供了美观时尚的主题界面以及交互功能。Qt Charts模块是基于Qt图形视图框架的,生成的图表可以很容易集成到QWidget、QGraphicsWidget或QML程序中。要使用Qt Charts模块,需要在安装Qt时选择安装Qt Charts组件,还需要在项目文件.pro中添加如下代码:QT += charts。

11.1 在Qt Widgets中使用Qt图表

Qt Charts模块中的QChart类用来管理不同类型的系列以及相关的图例、坐标轴等对象,QChart继承自 QGraphicsWidget,可以很容易在QGraphicsScene中使用。如果要在普通的QWidget部件中显示图表,那么可以借助QChartView类。

11.1.1 简单示例

  1. 新建Qt Widgets应用mycharts。在widget.cpp文件构造函数中添加如下代码:
QLineSeries* series = new QLineSeries();
series->append(0, 0);
series->append(2, 4);
QChartView *view = new QChartView(this);
view->chart()->addSeries(series);
view->resize(400, 300);        

这里的QLineSeries用来绘制折线图,它是一个线系列,通过直线将一系列的数据点进行相连。可以通过append()函数来向系列中添加数据点,其参数为(X, Y)坐标值。因为要在QWidget中使用图表,所以这里使用了QChartView,创建该类实例时会自动创建一个QChart对象,可以通过chart()函数来获取关联图表的指针。其实,Qt图表的主要功能都要由QChart类来完成,比如这里使用了addSeries()来添加系列,添加完成后图表会获得系列的拥有权。
在这里插入图片描述

  1. 使用默认坐标轴。
QLineSeries* series1 = new QLineSeries();
series1->append(0, 0);
series1->append(1, 4);
series1->append(3, 5);
view->chart()->addSeries(series1);
// 设置默认坐标轴
view->chart()->createDefaultAxes();
view->setRenderHint(QPainter::Antialiasing); 

上面向图表中添加了第2个线系列,然后使用QChart的createDefaultAxes()生成了默认的坐标轴,**注意,必须在所有系列都添加完毕后才能使用该函数生成默认坐标轴。**最后调用QChartView的setRenderHint(QPainter::Antialiasing)来启用抗锯齿,这样可以使折线绘制得更平滑。

  1. 设置图表标题和系列名称。
view->chart()->setTitle(tr("My Charts"));
view->chart()->setTitleBrush(Qt::darkYellow);
view->chart()->setTitleFont(QFont("Arial", 20));
series->setName("2020");
series1->setName("2021");      

使用setTitle()函数来为图表添加标题,并设置标题颜色和字体。通过使用setName()为系列设置名称,可以使其在图例中显示出来。
在这里插入图片描述

  1. 设置图例。
view->chart()->legend()->setMarkerShape(QLegend::MarkerShapeStar);
view->chart()->legend()->setBackgroundVisible(true);
view->chart()->legend()->setColor(QColor(255, 255, 255, 150));
view->chart()->legend()->setLabelColor(Qt::darkYellow);
view->chart()->legend()->setAlignment(Qt::AlignBottom);

可以通过QChart::legend()函数获取图表的图例对象,图例是一个图形对象,由QLegend类表示,该对象无法被创建或者删除。当系列发生变化时,QChart会更新图例的状态。还可以使用setBackgroundVisible(true)来显示图例背景,使用setBrush()、setLabelBrush()、setColor()、setLabelColor()、setFont()等函数来设置图例背景及标签的画刷、颜色等。默认情况下,图例附着在图表上,可以使用QLegend::detachFromChart()将其分离从而独立于图表进行布局。

  1. 设置图表及绘图区背景。
view->chart()->setBackgroundBrush(Qt::lightGray);
view->chart()->setPlotAreaBackgroundBrush(Qt::white);
view->chart()->setPlotAreaBackgroundVisible(true);
view->chart()->setBackgroundRoundness(15);
view->chart()->setDropShadowEnabled(true);   

使用QChart的setBackgroundBrush()可以设置背景画刷,默认是为整个图表设置背景。还可以通过setPlotAreaBackgroundBrush()为中间的绘图区设置背景,该背景默认是不显示的,如果需要设置该背景,需要调用setPlotAreaBackgroundVisible(true)。整个图表的背景默认是显示的,也可以通过setBackgroundVisible()进行设置是否显示。还可以通过setBackgroundRoundness()设置图表背景矩形的圆角弧度,使用setDropShadowEnabled(true)来启用阴影效果。
在这里插入图片描述

  1. QChart中还提供了几个现成的主题,可以通过setTheme()函数进行设置:
view->chart()->setTheme(QChart::ChartThemeBlueIcy);

在这里插入图片描述
在这里插入图片描述

  1. Qt图表还支持动画效果,可以通过QChart的setAnimationOptions()函数来设置动画选项。
    在这里插入图片描述
    如果开启了动画,可以使用setAnimationDuration()设置动画的持续时间,使用setAnimationEasingCurve()来设置动画使用的缓和曲线。
view->chart()->setAnimationOptions(QChart::AllAnimations);
view->chart()->setAnimationDuration(2000);
view->chart()->setAnimationEasingCurve(QEasingCurve(QEasingCurve::InQuad));

11.1.2 坐标轴

11.1.2.1 坐标轴分类

坐标轴用来设置一条包含刻度线、网格线和阴影的轴线,可以显示在图表的上、下、左、右等不同方向。每一个系列都可以绑定一个或多个水平和垂直坐标轴。Qt Charts支持下面这几种坐标轴类型,它们全部继承自QAbstractAxis类:
1)数值坐标轴QValueAxis:数值轴会直接向轴上添加实际的数值,该数值显示在刻度线的位置;
2)分类坐标轴QCategoryAxis:分类轴可以使用分类标签来区分基础数据,类别范围的宽度可以自由指定,分类标签显示在刻度线之间;
3)柱形图分类坐标轴QBarCategoryAxis:柱形图分类轴与分类轴类似,但是所有类别的范围宽度是一样的,分类标签显示在刻度线之间;
4)日期时间坐标轴QDateTimeAxis:在标签上可以显示日期或者时间信息,日期时间可以指定显示格式;
5)对数数值坐标轴QLogValueAxis:对数数值轴上的刻度是非线性的,它依赖于使用的数量级,轴上的每一个刻度数值都是前一个刻度数值乘以一个值;
6)颜色坐标轴QColorAxis:可以显示指定渐变的颜色比例。

11.1.2.2 数值坐标轴

QValueAxis *axisX = new QValueAxis;
axisX->setRange(0, 21);
axisX->setTickCount(6);
axisX->setMinorTickCount(1);
axisX->setLabelFormat("%.2f");
axisX->setLabelsAngle(30);
axisX->setLabelsColor(Qt::darkYellow);
view1->chart()->addAxis(axisX, Qt::AlignBottom);
series->attachAxis(axisX);
  1. 这里使用了数值坐标轴QValueAxis,可以使用setRange()来设置轴上最小值和最大值之间的范围,通过setTickCount()来设置刻度线数量,默认值为5,不能小于2;还可以使用setMinorTickCount()来设置次要刻度线的数量,就是在主要刻度线之间的网格线的数量,默认值为0;可以使用setLabelFormat()来设置标签格式,支持标准C++库函数printf()提供的各种格式控制符,如d、i、o、x、X、f、F、e、E、g、G、c等;还可以使用setLabelsAngle()、setLabelsColor()来设置标签的角度和颜色。
  2. 当设置好坐标轴以后,需要使用QChart::addAxis()将坐标轴添加到图表中,并指明对齐方式。要将一个系列与指定坐标轴进行关联,需要该系列调用attachAxis()来附着指定的轴,一个系列只能有一个横坐标轴和一个竖坐标轴。
    在这里插入图片描述

11.1.2.3 对数数值坐标轴

对数数值坐标轴QLogValueAxis,需要通过setBase()来指定对数的底数,轴上的每个刻度值都是前一个刻度值乘以底数,不需要指定刻度线数量。QLogValueAxis和QValueAxis都继承自QAbstractAxis,它们的一些用法是相似的。

QLogValueAxis *axisY = new QLogValueAxis;
axisY->setBase(2);
axisY->setRange(8, 260);
axisY->setMinorTickCount(1);
view1->chart()->addAxis(axisY, Qt::AlignLeft);
series->attachAxis(axisY);

在这里插入图片描述

11.1.2.4 柱形图分类坐标轴

  1. 柱形图系列由QBarSeries类表示,会将数据绘制为一系列按类别分组的竖条,每个类别从添加到系列中的每个柱形集QBarSet中提取一条。QBarSet作为柱形集包含了每个类别中的一个数据值,可以通过append()来添加一个值或者值的列表,也可以使用流运算符添加。
QBarSet *set0 = new QBarSet("Jane");
QBarSet *set1 = new QBarSet("John");
QBarSet *set2 = new QBarSet("Axel");
*set0 << 1 << 2 << 3 << 4 << 5 << 6;
*set1 << 5 << 0 << 0 << 4 << 0 << 7;
*set2 << 3 << 5 << 8 << 13 << 8 << 5;
QBarSeries *series1 = new QBarSeries();
series1->append(set0);
series1->append(set1);
series1->append(set2);
view2->chart()->addSeries(series1);
  1. 下面来添加柱形图分类坐标轴,柱形图分类坐标轴由QBarCategoryAxis表示,可以通过append()来添加分类,类别名称会显示在刻度之间。
QStringList categories;
categories << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";
QBarCategoryAxis *axisX1 = new QBarCategoryAxis();
axisX1->append(categories);
view2->chart()->addAxis(axisX1, Qt::AlignBottom);
series1->attachAxis(axisX1);

在这里插入图片描述

11.1.2.5 分类坐标轴

分类坐标轴QCategoryAxis,它继承自QValueAxis。与柱形图分类坐标轴QBarCategoryAxis不同,QCategoryAxis可以指定分类的宽度。可以通过append()来添加新的类别,其中需要指定分类标签和该分类的最大值。还可以通过setStartValue()来设置第一个分类的最小值。

QCategoryAxis *axisY1 = new QCategoryAxis;
axisY1->append("Low", 5);
axisY1->append("Medium", 10);
axisY1->append("High", 15);
view2->chart()->addAxis(axisY1, Qt::AlignLeft);
series1->attachAxis(axisY1);

在这里插入图片描述

11.1.2.6 堆积柱形图和百分比堆积柱形图

  1. 与柱形图QBarSeries相似的,还有堆积柱形图QStackedBarSeries和百分比堆积柱形图QPercentBarSeries。
    1)QStackedBarSeries会将一类柱形条堆积在一个垂直柱形条上,每个柱形集中对应分类的柱形条都作为这个垂直柱形条的一段;
    在这里插入图片描述

2)QPercentBarSeries与QStackedBarSeries类似,只是所有堆积柱形条都是等长的,而其中的分段柱形会根据代表的数值在总值中的占比绘制为不同的长度。
在这里插入图片描述

  1. 只需要将代码中QBarSeries替换为QStackedBarSeries或者QPercentBarSeries就可以查看另外两种柱形图的效果。与它们3个对应的还有3个水平柱形图 QHorizontalBarSeries、QHorizontalStackedBarSeries和QHorizontalPercentBarSeries。

11.1.3 使用外部数据动态创建图表

  1. 图表是用来显示数据的,实际编程中一般要使用数据库或者XML来作为数据源提供数据。
  2. 在Qt Charts模块中提供了一些模型映射类,可以让各个图表使用QAbstractItemModel的子类作为数据源,这些类均以ModelMapper结尾,可以在帮助中通过Qt Charts C++ Classes关键字查看相关内容。
    在这里插入图片描述
  3. 通过使用这些映射器,可以将数据模型中指定的数据全部显示到图表上,还可以随着数据模型中数据的变化而自动更新显示。除了使用这种方式,有时还希望将模型中的数据一个一个动态显示到图表上,这个可以使用定时器更新图表的绘图区域来实现。
  4. QVXYModelMapper类,被称为垂直模型映射器,可以将折线图、曲线图或散点图与一个数据模型进行关联,在这个数据模型中需要包含两列数值来分别为数据点提供X、Y坐标。可以分别通过setModel()和setSeries()来设置模型和系列,然后通过setXColumn()和setYColumn()来指定模型中的字段为X和Y坐标提供数值。这里分别使用m_xy表中的m_x和m_y字段来为QSplineSeries的数据点提供X和Y坐标,表中的每一行记录都表示为了一个数据点。
// 初始化模型和视图
model = new QSqlTableModel(this);
model->setTable("m_xy");
model->select();
model->setHeaderData(0, Qt::Horizontal, tr("序号"));
model->setHeaderData(1, Qt::Horizontal, tr("X轴"));
model->setHeaderData(2, Qt::Horizontal, tr("Y轴"));
QTableView *view = new QTableView(this);
view->setModel(model);
view->resize(320, 300);
view->move(10, 10);
... ...
// 设置图表视图、添加系列和轴
chartView = new QChartView(this);
chartView->resize(400, 300);
chartView->setRenderHint(QPainter::Antialiasing);
chartView->move(350, 10);
chartView->chart()->legend()->setVisible(false);
chartView->chart()->setAnimationOptions(QChart::AllAnimations);
chartView->chart()->setTheme(QChart::ChartThemeBlueIcy);
series = new QSplineSeries;
chartView->chart()->addSeries(series);
axisX = new QValueAxis;
axisX->setRange(0, 10);
axisX->setTickCount(11);
axisX->setLabelFormat("%d");
chartView->chart()->addAxis(axisX, Qt::AlignBottom);
series->attachAxis(axisX);
QValueAxis *axisY = new QValueAxis;
axisY->setRange(0, 10);
axisY->setTickCount(6);
axisY->setMinorTickCount(1);
chartView->chart()->addAxis(axisY, Qt::AlignLeft);
series->attachAxis(axisY);
... ...
// 使用模型映射器关联模型中的数据到图表系列
QVXYModelMapper *mapper = new QVXYModelMapper(this);
mapper->setSeries(series);
mapper->setModel(model);
mapper->setXColumn(1);
mapper->setYColumn(2);

在这里插入图片描述

  1. 通过定时器为图表动态添加数据
    1)先开启一个间隔2S的定时器。并进行定时器溢出信号和自定义槽的关联。
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &Widget::handleTimeout);
timer->start(2000);

2)下面来添加定时器溢出信号关联的槽的实现:

void Widget::handleTimeout()
{
    if (id < model->rowCount()) {
        int m_x = model->data(model->index(id, 1)).toInt();
        int m_y = model->data(model->index(id, 2)).toInt();
        series->append(m_x, m_y);
        if (m_x > axisX->max() - 3) {
            int temp = model->data(model->index(id-1, 1)).toInt();
            qreal width = chartView->chart()->plotArea().width();
            qreal dx = width / (axisX->tickCount()-1) *(m_x - temp);
            chartView->chart()->scroll(dx, 0);
        }
        id++;
    } else timer->stop();
}

这里就是获取数据模型中的数据值添加到图表系列中,然后更新图表的显示区域,这个是通过QChart::scroll()来实现的,它可以根据指定的距离来滚动图表的可见区域。
在这里插入图片描述

11.2 在Qt Quick中使用Qt图表

Qt Charts模块同时提供了C++和QML两套 API,所以在Qt Widgets编程中的内容,在Qt Quick编程中也有相似的功能,要在Qt Quick中使用Qt Charts模块,需要使用如下导入语句:import QtCharts。

11.2.1 创建一个图表项目

  1. 打开Qt Creator,选择“文件→New Project”菜单项,模板选择其他项目分类中的Empty qmake Project,填写项目名称为mycharts。项目创建完成后打开mycharts.pro文件,添加如下代码并保存该文件:
QT += quick widgets charts

然后添加main.qml文件。按下Ctrl+N向项目中添加新文件,模板选择Qt分类中的QML File(Qt Quick 2),名称设置为main.qml。完成后将其内容修改为:

import QtQuick
import QtCharts

Window {
    visible: true
    width: 640; height: 480

    ChartView {
        title: "Line"
        anchors.fill: parent
        antialiasing: true

        LineSeries {
            name: "LineSeries"
            XYPoint { x: 0; y: 0 }
            XYPoint { x: 1.1; y: 2.1 }
            XYPoint { x: 1.9; y: 3.3 }
        }
    }
}

代码中的LineSeries用来绘制折线图,其中name属性就是系列的名称,会显示为该系列的图例,XYPoint 对象用来提供静态坐标数据,这里一共设置了3个点。所有的系列都需要放到ChartView 类型中进行显示。

  1. 最后添加main.cpp文件。继续添加新文件,选择C/C++ Source File模板,名称设置为main.cpp,完成后修改其内容如下:
#include <QtWidgets/QApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl::fromLocalFile("../mycharts/main.qml"));

    return app.exec();
}

在这里插入图片描述

需要注意,从Qt Creator 3.0开始,使用Qt Quick Application向导创建的项目会基于Qt Quick 2模板,默认会使用QGuiApplication,而Qt Charts依赖于Qt的Graphics View Framework图形视图框架进行渲染,需要使用QApplication。所以,如果使用了Qt Quick Application向导创建项目,那么需要在main.cpp文件中使用QApplication代替QGuiApplication。

11.2.2 坐标轴Axes

  1. 坐标轴可以用来显示刻度线、网格线和阴影等,与Qt Widgets编程中相似,Qt Charts在Qt Quick中支持下面这几种坐标轴类型,它们全部继承自AbstractAxis类型:
    1)数值坐标轴ValueAxis
    2)分类坐标轴CategoryAxis
    3)柱形图分类坐标轴BarCategoryAxis
    4)日期时间坐标轴DateTimeAxis
    5)对数数值坐标轴LogValueAxis
  2. 同一个图表可以使用多个不同类型的坐标轴,它们可以设置在图表的上、下、左、右等不同方向。

11.2.2.1 数值坐标轴和对数数值坐标轴

ValueAxis {
    id: xAxis
    min: 0; max: 1000; labelFormat: "%.1f"
    minorTickCount: 1; tickCount : 5
}

LineSeries {
    name: "LineSeries"
    axisX: xAxis

    XYPoint { x: 0; y: 0 }
    XYPoint { x: 100; y: 200 }
    XYPoint { x: 300; y: 500 }
    XYPoint { x: 600; y: 400 }
}
  1. 示例中使用数值坐标轴ValueAxis作为了LineSeries的横轴,可以通过axisX 属性来指定系列的横坐标轴。对于ValueAxis对象,min、max属性可以设置轴的最小值和最大值;labelFormat 属性可以设置标签格式,支持标准C++库函数printf()提供的各种格式控制符;minorTickCount 属性用来指定次要刻度线的数量,默认为0;tickCount 属性用来指定轴上的刻度线数量,默认值是5,不能小于2。
    在这里插入图片描述

  2. 这里默认显示的刻度值是将最大值减去最小值,然后根据刻度线的数量进行均分,当调用applyNiceNumbers()函数后,为了使刻度值更美观,会自动调整刻度线的数量。刻度值显示有两种类型,由tickType属性指定,默认的这种是ValueAxis.TicksFixed,还有一种动态的ValueAxis.TicksDynamic,它会根据tickAnchor和 tickInterval两个属性来设置刻度线的位置。
    在这里插入图片描述

  3. 对数数值坐标轴LogValueAxis用法与数值坐标轴ValueAxis相似,只需要指定对数的底数base属性即可。

11.2.2.2 分类坐标轴

CategoryAxis {
    id: yAxis
    min: 0; max: 700
    labelsPosition : CategoryAxis.AxisLabelsPositionOnValue
    
    CategoryRange { label: "critical"; endValue: 200 }
    CategoryRange { label: "low"; endValue: 400 }
    CategoryRange { label: "normal"; endValue: 700 }
}

分类坐标轴CategoryAxis中可以使用CategoryRange子对象来指定标签和范围,标签默认显示在范围中间,可以通过labelsPosition属性让其显示在刻度值处。另外,CategoryAxis类型中还提供了startValue属性用来指定第一个分类的最小值;categoriesLabels属性用来获取所有标签的字符串列表;count属性用来获取分类数量;append()、remove()和replace()等函数用来修改分类。
下面在LineSeries 中指定纵轴:axisY: yAxis。
在这里插入图片描述

11.2.2.3 柱形图分类坐标轴

ChartView {
    title: "BarSeries"
    anchors.fill: parent; antialiasing: true

    BarSeries {
        axisX: BarCategoryAxis { categories: ["2007", "2008", "2009",
                "2010", "2011", "2012" ] }
        BarSet { label: "Bob"; values: [2, 2, 3, 4, 5, 6] }
        BarSet { label: "Susan"; values: [5, 1, 2, 4, 1, 7] }
        BarSet { label: "James"; values: [3, 5, 8, 13, 5, 8] }
    }
}

柱形图分类坐标轴BarCategoryAxis用于柱形图中。这里使用BarSeries来创建一个柱形图,BarCategoryAxis做为柱形图的横坐标轴,在其中一般只需要设置分类信息categories属性即可,它是一个字符串列表。柱形图中使用 BarSet子对象来为各个分类提供数据集,包括了名称和各个分类对应的值。
在这里插入图片描述

11.2.2.4 日期时间坐标轴

ChartView {
    title: "LineSeries"; anchors.fill: parent; antialiasing: true
    DateTimeAxis {
        id: xAxis;format: "MM-dd"; tickCount: 5
        min: new Date(2019, 0, 15)  // 2019-1-15
        max: new Date(2019, 2, 1)  // 2019-3-1
    }
    LineSeries {
        name: "LineSeries"; axisX: xAxis
        
        XYPoint { x: toMsecsSinceEpoch(new Date(2019, 0, 20)); y: 12 }
        XYPoint { x: toMsecsSinceEpoch(new Date(2019, 1, 13)); y: 18 }
        XYPoint { x: toMsecsSinceEpoch(new Date(2019, 1, 20)); y: 30 }
    }
}
function toMsecsSinceEpoch(date) {
    var msecs = date.getTime(); return msecs;
}

日期时间坐标轴DateTimeAxis,可以将日期时间作为刻度值。format用来设置刻度标签显示格式;然后是使用JavaScript的Date对象来设置日期时间时,中间表示月份的参数介于0到11之间,所以1月份需要设置为0;还有就是在LineSeries上的点只能用数值表示,所以需要将日期时间格式转换为数值,这个可以通过JavaScript的getTime()方法来获取,它返回从1970年1月1日至今的毫秒数,为了更加清晰,这里自定义了一个toMsecsSinceEpoch()函数。
在这里插入图片描述

11.2.2.5 坐标轴的共有属性

前面提到的所有坐标轴类型全部继承自AbstractAxis类型,所以它们都可以使用AbstractAxis的属性。通过这些属性可以单独控制坐标轴的各种元素,包括轴线、标题、标签、网格线、阴影等。例如:

color: "blue"
gridLineColor: "lightgreen"
labelsAngle: 90
labelsColor: "red"
labelsFont { bold: true; pixelSize: 15 }
shadesVisible: true
shadesColor: "lightgrey"
titleText: "date"
titleFont { bold: true; pixelSize: 30 }

在这里插入图片描述

11.2.3 图例Legend

  1. Legend类型用来显示图表的图例,Legend对象可以通过ChartView进行引用,当图表中系列改变时,ChartView会自动更新图例的状态。
  2. Legend类型包含的属性如下表所列,但是并没有提供用于修改图例标记的接口,如果想修改图例标记可以创建自定义图例。
    在这里插入图片描述
ChartView {
    title: "Bar series"
    anchors.fill: parent; antialiasing: true

    legend {
        alignment: Qt.AlignBottom
        backgroundVisible: true
        color: "lightblue"; borderColor: "blue"; labelColor: "gold"
        font.bold: true; font.pointSize: 15
        markerShape: Legend.MarkerShapeCircle
    }

    BarSeries {
        id: mySeries
        axisX: BarCategoryAxis { categories: ["2007", "2008", "2009" ] }
        BarSet { label: "Bob"; values: [2, 2, 3] }
        BarSet { label: "Susan"; values: [5, 1, 2] }
        BarSet { label: "James"; values: [3, 5, 8] }
    }
}

在这里插入图片描述

11.2.4 ChartView

  1. 可以通过ChartView来显示一个图表,其实,是由ChartView将系列、坐标轴、图例等元素组合到一起形成了一个完整的图表。
  2. 可以使用title属性来设置图表的标题,titleColor和titleFont用来设置标题的颜色和字体;plotAreaColor用来设置中间绘图区的颜色;backgroundColor设置整个图表的背景色,如果没有设置plotAreaColor,那么中间的绘图区也显示背景色;backgroundRoundness可以设置图表背景矩形的圆角弧度;dropShadowEnabled设置图表背景是否使用阴影效果。
  3. 虽然可以使用属性来简单自定义图表外观,但组合一个漂亮的主题还是需要费些功夫的。ChartView中为我们提供了几个内建的主题。ChartView的主题会涉及图表的所有可视化元素,包括系列、坐标轴和图例的颜色、画笔、画刷、字体等。
  4. ChartView还可以选择是否启用动画效果,包括系列动画和网格轴动画,由animationOptions属性指定。另外可以使用animationDuration属性指定动画的持续时间,使用animationEasingCurve设置缓和曲线。
ChartView {
    title: qsTr("我的图表"); titleColor: Qt.lighter("blue")
    titleFont{ bold: true; pointSize: 20}
    plotAreaColor: "lightgrey"
    backgroundColor: Qt.lighter("red"); backgroundRoundness: 25
    dropShadowEnabled: true

    animationOptions: ChartView.AllAnimations
    animationDuration: 5000
    animationEasingCurve: Easing.InQuad

    anchors.fill: parent; anchors.margins: 20
    antialiasing: true

    LineSeries {
        name: "LineSeries"
        XYPoint { x: 0; y: 0 }
        XYPoint { x: 1.1; y: 2.1 }
        XYPoint { x: 1.9; y: 3.3 }
    }
}

在这里插入图片描述

11.2.5 使用数据动态创建图表

在实际应用中大多是从外部读取数据来动态创建图表。如下将从模型中动态读取数据来创建图表。

Window {
    visible: true
    width: 640; height: 480
    property int currentIndex: -1

    ChartView {
        id: chartView
        anchors.fill: parent
        title: qsTr("我的网站访问量")
        theme: ChartView.ChartThemeBlueCerulean
        antialiasing: true
    }
}
// 通过一个ListModel来模拟数据源
ListModel {
    id: listModel
    
    ListElement { month: 1; pv: 205864 }
    ListElement { month: 2; pv: 254681 }
    ListElement { month: 3; pv: 306582 }
    ListElement { month: 4; pv: 284326 }
    ListElement { month: 5; pv: 248957 }
    ListElement { month: 6; pv: 315624 }
}
Timer {
    id: timer
    interval: 1500; repeat: true
    triggeredOnStart: true; running: true
    onTriggered: {
        currentIndex++;
        if (currentIndex < listModel.count) {
            var lineSeries = chartView.series("2018");
            // 第一次运行时创建曲线
            if (!lineSeries) {
                lineSeries = chartView.createSeries(ChartView.SeriesTypeSpline,"2018");
                chartView.axisY().min = 200000;
                chartView.axisY().max = 320000;
                chartView.axisY().tickCount = 6;
                chartView.axisY().titleText = qsTr("PV");
                chartView.axisX().visible = false
                lineSeries.color = "#87CEFA"
                lineSeries.pointsVisible = true
                lineSeries.pointLabelsVisible = true
                lineSeries.pointLabelsFormat = qsTr("@xPoint月份PV:@yPoint")
                chartView.animationOptions = ChartView.SeriesAnimations
            }
            lineSeries.append(listModel.get(currentIndex).month, listModel.get(currentIndex).pv);

					if (listModel.get(currentIndex).month > 3) {
    						chartView.axisX().max = Number(listModel.get(currentIndex).month) + 1;
    						chartView.axisX().min = chartView.axisX().max - 5;
					} else {
    						chartView.axisX().max = 5;
    						chartView.axisX().min = 0;
					}
					chartView.axisX().tickCount = chartView.axisX().max - chartView.axisX().min + 1;
		} else {
				timer.stop();
				chartView.axisX().min = 0;
		}	 
	} 
}

在这里插入图片描述

11.2.6 常用图表类型介绍

在Qt Charts模块中还包括散点图、面积图、饼状图、盒须图等其他类型的图表,它们用法相似。

  1. 折线图、曲线图和散点图
    散点图与折线图和曲线图用法相似。折线图LineSeries、曲线图SplineSeries和散点图ScatterSeries都继承自XYSeries,它们的共同特点是显示的信息都是由XYPoint指定的数据点。在XYSeries类型中定义的属性、信号和方法在这3个图表类型中都可以使用。
    在这里插入图片描述
  2. 面积图
    面积图AreaSeries用来显示一定量的数据,强调数据随时间变化的程度。面积图基于折线图,可以通过upperSeries属性来指定一个折线系列作为区域的上边界,默认的下边界是可绘制区域的下边界,然后填充颜色。当然,也可以通过lowerSeries来指定另外一个折线系列作为图形的下边界。
    在这里插入图片描述
  3. 柱形图、堆积柱形图、百分比堆积柱形图
    1)柱形图通过水平或垂直的按类分组的柱形条来表示数据,柱形图BarSeries类型可以使用按类分组的垂直柱形条来表示数据,每一类(categories)都包含了所有柱形集BarSet的一个柱形条。
    2)在堆积柱形图StackedBarSeries中,一类柱形条会堆积在一个垂直柱形条上,每个柱形集中对应分类的柱形条都作为这个垂直柱形条的一段。
    在这里插入图片描述

3)百分比堆积柱形图PercentBarSeries与堆积柱形图类似,只是所有堆积柱形条都是等长的,而其中的分段柱形会根据代表的数值在总值中的占比绘制为不同的长度。
在这里插入图片描述

这3种柱形图的代码可以通用,比如前面使用BarSeries的示例,可以直接更改类型名称为StackedBarSeries或者PercentBarSeries来使用其他两种类型。

  1. 饼状图
    饼状图PieSeries由PieSlice类型定义的切片组成,PieSeries可以通过计算一个切片在总切片中占得百分比来决定该切片在饼状图中的大小。默认的,饼状图被定义为一个完整的饼状,也可以通过设置开始角度startAngle和结束角度endAngle来创建部分饼图。一个完整的饼图为360度,12点钟方向为0。可以通过find(string label)或者at(int index)来获取一个指定的切片,切片的exploded属性可以设置该切片与饼状图分离,从而突出显示。
    在这里插入图片描述

  2. 盒须图(箱形图)
    盒须图BoxPlotSeries又称为箱形图,因其形状如箱子而得名,常用于品质管理。盒须图中的盒须项由BoxSet类型指定,它是五个不同数值的图形表示,这五个数值按最小值、下四分位数、中位数、上四分位数和最大值的顺序进行指定。
    在这里插入图片描述

  3. 蜡烛图(K线图)
    蜡烛图CandlestickSeries又称为K线图,常用于股市和期货市场。蜡烛图中的蜡烛项由CandlestickSet类型指定,它是五个数值的图形表示:open、high、low、close和timestamp。需要注意的是,在一个蜡烛图中,每个timestamp必须是唯一的。
    在这里插入图片描述

  4. 极坐标图
    极坐标图PolarChartView在一个圆图中来展示数据,在这个圆图中的数据点通过一个夹角和一段相对于极点(中心点)的距离来表示。PolarChartView是对ChartView类型的特例化,支持折线系列、曲线系列、面积系列和散点系列,以及这些系列所支持的坐标轴类型,每一个坐标轴既可以作为径向轴也可以作为角轴。
    在这里插入图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐