Qt图表绘制(QtCharts)-绘制简单的盒须图[箱形图](12)✌
文章目录
- Qt图表绘制(QtCharts)-绘制简单的盒须图[箱形图](12)✌
- 1、概述🤏
- 2、实现步骤🤞
- 3、主要使用的类🤟
- 4、主要代码🤘
- 5、实现效果🤛
- 6、源代码👍
更多精彩内容 |
---|
👉个人内容分类汇总 👈 |
注意:我使用的QtCharts是基于Qt 5.12.12版本 |
1、概述🤏
Qt Charts 模块提供了一组易于使用的图表组件,能够创建时尚、交互式、以数据为中心的用户界面。
它使用
Qt Graphics View
框架,因此可以轻松地将图表集成到现代用户界面中。Qt Charts 可以用作 QWidgets、QGraphicsWidget 或 QML 类型。 用户可以通过选择图表主题之一轻松创建令人印象深刻的图表。
这一个Demo干了啥:🤏🤏🤏
- 在
initChart()
函数中演示了如何使用QtCharts绘制简单的的盒须图(箱形图);- Qt示例中通过继承
QTextStream
类实现读取数据功能,感觉过于复杂,为了便于学习将读取数据功能直接封装成一个getData()
函数;- 在源码中包含使用的详细注释和注意事项 ;
- 将UI和代码分离,使实现图表绘制的代码更单一简洁,便于学习。
2、实现步骤🤞
-
打开
.pro
文件,输入Qt += charts
,引入Qt Charts模块; -
打开ui设计器,选择一个
Graphics View
控件,鼠标右键提升为; -
输入
QChartView
,点击添加、提升; -
在窗口右上角就可以看见控件类型变成
QChartView
了,然后将控件命名为chartView; 注意:由于QChartView需要引入命名空间,所以这里提升后编译时不通过的。 -
在代码中添加QtCharts头文件,引入命名空间;一般我们最好在
cpp文件
中添加头文件和引入命名空间,尽量避免在.h文件
中引入(这里为了方便,代码简洁直接在头文件中引入命名空间),而在cpp文件中引入命名空间需要在ui_widget.h文件前,否则编译会失败,因为在ui文件中会用到QChartView类。#include <QtCharts> // 导入QtCharts所有的头文件,也可以单独导入某一个// 引入qchart命名空间(注意:如果是在ui中提升为QChartView, // 则QT_CHARTS_USE_NAMESPACE一定要放在#include "ui_widget.h"前面,否则编译会失败) QT_CHARTS_USE_NAMESPACE
3、主要使用的类🤟
类名 | 作用 |
---|---|
QBoxPlotSeries | 创建一个用于绘制盒须图的数据集对象 |
QBoxSet | 单个盒须图数据对象,由下限、下四分位数、中位数、上四分位数和上限五个值组成 |
QAbstractAxis | 坐标轴基类 |
4、主要代码🤘
widget.h
文件
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QBoxPlotSeries>
QT_CHARTS_USE_NAMESPACE // 引入命名空间,必须放在ui_widget.h前QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:void initChart(); // 初始化绘制图表QList<QBoxSet *> getData(); // 获取用于绘制的盒须图数据qreal findMedian(QList<qreal>& sortedList, int begin, int end);private:Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
文件
#include "widget.h"
#include "ui_widget.h"#include <qdebug.h>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setWindowTitle("QtCharts绘图-盒须图(箱型图)Demo");initChart();
}Widget::~Widget()
{delete ui;
}/*** @brief 初始化绘制图表*/
void Widget::initChart()
{QBoxPlotSeries* series = new QBoxPlotSeries(); // 创建一个用于绘制盒须图的数据集对象series->setName("XXX公司");series->append(getData()); // 读取资源文件中的数据并添加进seriesQChart* chart = ui->chartView->chart();chart->addSeries(series); // 将需要绘制的数据集(series)添加进char中chart->setTitle("盒须图标题"); // 设置图表标题chart->setAnimationOptions(QChart::SeriesAnimations); // 设置图表显示的动画(对性能有影响)chart->createDefaultAxes(); // 根据已有的series生成对应类型的XY轴QAbstractAxis* axisY = chart->axes(Qt::Vertical).first(); // 获取Y轴axisY->setRange(15, 35); // 设置Y轴范围,让图表更容易观看(Qt的示例中这里有bug,设置成了X轴)chart->legend()->setVisible(true); // 显示图例chart->legend()->setAlignment(Qt::AlignBottom); // 设置图例显示位置ui->chartView->setChart(chart);ui->chartView->setRenderHint(QPainter::Antialiasing); // 设置抗锯齿
}/*** @brief 读取资源文件,返回用于绘制的盒须图数据* @return 返回用于绘制的数据,如果count为0则没有可用数据*/
QList<QBoxSet *> Widget::getData()
{QList<QBoxSet *> dataList;QList<qreal> sortedList;QFile file(":/acme.txt");if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) // 文件打开失败return dataList;while (!file.atEnd()){QString line = file.readLine();if(line.isEmpty() || line.startsWith("#")) // 如果数据无效则跳过continue;QStringList strList = line.split(" ", QString::SkipEmptyParts); // 以空格拆分字符串sortedList.clear();for(int i = 1; i < strList.count(); i++){sortedList.append(strList.at(i).toDouble());}std::sort(sortedList.begin(), sortedList.end()); // 由于qt中提示qSort过时了,推荐使用std::sortint count = sortedList.count();QBoxSet* box = new QBoxSet(); // 创建盒须图的一个数据(由下限、下四分位数、中位数、上四分位数和上限 五个值组成)box->setLabel(strList.first()); // 设置标签box->setValue(QBoxSet::LowerExtreme, sortedList.first()); // 下极限box->setValue(QBoxSet::UpperExtreme, sortedList.last()); // 上极限box->setValue(QBoxSet::Median, findMedian(sortedList, 0, count)); // 中位数box->setValue(QBoxSet::LowerQuartile, findMedian(sortedList, 0, count / 2)); // 下四分位数box->setValue(QBoxSet::UpperQuartile,findMedian(sortedList, (count / 2) + (count % 2), count)); // 上四分位数,(count % 2)当数据个数为奇数时向上取整dataList.append(box);}return dataList;
}/*** @brief 计算数组中的中位数,如果设置起始终止位置可用计算(下上四分位数、上四分位数)* @param sortedList 需要计算中位数的数组* @param begin 起始位置* @param end 中止位置* @return 中位数(下四分位数、上四分位数)*/
qreal Widget::findMedian(QList<qreal> &sortedList, int begin, int end)
{int count = end - begin;if(count % 2){return sortedList.at(count / 2 + begin);}else // 如果需要计算的数是偶数,则取两个数的平均值{qreal right = sortedList.at(count / 2 + begin);qreal left = sortedList.at(count / 2 - 1 + begin);return (right + left) / 2.0;}
}
- 资源文件
came.txt
# 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
5、实现效果🤛
6、源代码👍
gitee
github
☝☝☝☝☝☝☝☝☝☝☝☝☝☝☝☝☝☝☝☝☝