Qt+ECharts开发笔记(四):ECharts的饼图介绍、基础使用和Qt封装百分比图Demo
前言
前一篇介绍了横向柱图图。本篇将介绍基础饼图使用,并将其封装一层Qt。
本篇的demo使用隐藏js代码的方式,实现了一个饼图的基本交互方式,并预留了Qt模块对外的基础接口。
Demo演示
ECharts代码效果调试
使用ECharts的在线调试器,先调试出大致预期的效果。
option = {
legend: {
top: '90%',
show: false
},
series: [
{
selectedMode: 'single', // 选择模式
selectedOffset: 10, // 选取后偏移,需要先设置选择模式才生效
type: 'pie', // 图例类型
radius: ['60%', '90%'], // 同心圆双边界区域
itemStyle: { // 数据项样式
borderRadius: 0, // 边界圆角
borderColor: '#FF0000', // 边界颜色
borderWidth: 0 // 边界宽度
},
label: {
show: true,
fontSize: '32',
fontWeight: 'bold',
formatter: '{b}\n\n{d}%',
position: 'center'
},
emphasis: {
// 高亮状态的扇区和标签样式
label: {
show: false,
fontSize: '32',
fontWeight: 'bold'
}
},
labelLine: {
show: true
},
data: [
{
value: 5.6,
name: '开机率',
itemStyle: {
color: 'rgb(41, 235, 255)',
shadowBlur: 10, // 外阴影
shadowOffsetX: 0, // 外阴影x轴偏移
shadowOffsetY: 0, // 外阴影y轴偏移
shadowColor: 'rgb(41, 235, 255)' // 外阴影颜色
}
},
{
value: 5.2,
name: '',
itemStyle: {
color: 'rgba(45,62,113)',
shadowBlur: 10,
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowColor: 'rgba(45,62,113)'
}
}
]
}
]
};
Qt封装动态ECharts
步骤一:静态html
此系列的标准html文件。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ECharts</title>
<script src="./echarts.js"></script>
</head>
<body>
<style>
#main,
html,
body{
width: 100%;
height: 100%;
overflow: hidden;
}
#main {
width: 95%;
height: 95%;
}
</style>
<div id="main"></div>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
window.onresize = function() {
myChart.resize();
};
</script>
</body>
</html>
步骤二:初始化
这里是我们不让鼠标点击,只用于观看,鼠标相关的效果EChart4和EChart5也有一些不同,ECharts4交互的坑,查看本文章最后“入坑“章节。
void PieEChartWidget::initControl()
{
_pLabelCenterUp = new QLabel(this);
_pLabelCenterUp->raise();
_pLabelCenterUp->setAlignment(Qt::AlignBottom | Qt::AlignHCenter);
_pLabelCenterUp->setText(QSTRING("开机率"));
_pLabelCenterUp->setStyleSheet("font-size: 36px;"
"font-weight: bold;"
"align: top ;"
"color: rgb(41, 235, 255);"
"padding: 0 30 10 0;");
_pLabelCenterDown = new QLabel(this);
_pLabelCenterDown->raise();
_pLabelCenterDown->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
_pLabelCenterDown->setText(QSTRING("%1%").arg(0));
_pLabelCenterDown->setStyleSheet("font-size: 64px;"
"font-weight: bold;"
"align: center;"
"color: rgb(41, 235, 255);"
"padding: 0 30 0 0;");
_pWebEngineView = new QWebEngineView(this);
_pWebEnginePage = new QWebEnginePage(this);
_pWebChannel = new QWebChannel(this);
QString filePath;
#if 0
// 使用绝对路径
filePath = QString("%1/%2").arg(_htmlDir).arg(_indexFileName);
#else
// 使用资源路径
filePath = "qrc:/pieEChartWidget/html/eChartWidget.html";
#endif
LOG << "file exist:" << QFile::exists(filePath) << filePath;
#if 0
// 打印html文件内容
QFile file(_indexFilePath);
file.open(QIODevice::ReadOnly);
LOG << QString(file.readAll());
file.close();
#endif
connect(_pWebEnginePage, SIGNAL(loadFinished(bool)), this, SLOT(slot_loadFinished(bool)));
_pWebEnginePage->load(QUrl(filePath));
_pWebEnginePage->setWebChannel(_pWebChannel);
_pWebEngineView->setPage(_pWebEnginePage);
// 背景透明
// _pWebEngineView->setStyleSheet("background-color: transparent");
_pWebEnginePage->setBackgroundColor(Qt::transparent);
// 鼠标穿透
_pWebEngineView->setAttribute(Qt::WA_TransparentForMouseEvents, true);
}
步骤三:将需要的接口预留
设置百分数,文本上要注意位置偏移,手动进行校准:
void PieEChartWidget::setPercent(double percent)
{
if(percent < 0 || percent > 100)
{
return;
}
LOG << percent;
if(percent == 100)
{
_pLabelCenterDown->setText(QSTRING("100%"));
}else{
if(_percent < 10)
{
_pLabelCenterDown->setText(QSTRING("%1%").arg(percent, 0, 'g', 2));
}else{
_pLabelCenterDown->setText(QSTRING(" %1%").arg(percent, 0, 'g', 2));
}
}
QString jsStr = QSTRING(
"option.series[0].data[0].value = %1;"
"option.series[0].data[1].value = %2;"
"myChart.setOption(option, true);")
.arg(percent)
.arg(100 - percent);
LOG << jsStr;
_percent = percent;
runJsScript(jsStr);
}
步骤四:动态操作
重置
void PieEChartWidget::on_pushButton_reset_clicked()
{
initJs();
}
刷新
void PieEChartWidget::on_pushButton_flush_clicked()
{
QString jsStr =
"var empty = {};"
"myChart.setOption(empty, true);"
"myChart.setOption(option, true);";
runJsScript(jsStr);
}
随机生成(使用Qt代码)
void PieEChartWidget::on_pushButton_createRandom_clicked()
{
float value = qrand() % 10001 / 100;
setPercent(value);
}
清除数据
void PieEChartWidget::on_pushButton_clear_clicked()
{
setPercent(0.0f);
}
指定值
void PieEChartWidget::on_doubleSpinBox_valueChanged(double arg1)
{
setPercent(ui->doubleSpinBox->value());
}
Demo源码
PieEChartWidget.h
#ifndef PIEECHARTWIDGET_H
#define PIEECHARTWIDGET_H
#include <QWidget>
#include <QWebEngineView>
#include <QWebEnginePage>
#include <QWebChannel>
#include <QLabel>
namespace Ui {
class PieEChartWidget;
}
class PieEChartWidget : public QWidget
{
Q_OBJECT
public:
explicit PieEChartWidget(QWidget *parent = 0);
~PieEChartWidget();
public:
void setPercent(double percent);
protected:
void initControl();
protected slots:
void slot_loadFinished(bool result);
protected:
void initJs();
protected:
void runJsScript(QString str);
protected:
void resizeEvent(QResizeEvent *event);
private slots:
void on_pushButton_clear_clicked();
void on_pushButton_flush_clicked();
void on_pushButton_createRandom_clicked();
void on_pushButton_reset_clicked();
void on_doubleSpinBox_valueChanged(double arg1);
private:
Ui::PieEChartWidget *ui;
private:
QWebEngineView *_pWebEngineView; // 浏览器窗口
QWebEnginePage *_pWebEnginePage; // 浏览器页面
QWebChannel *_pWebChannel; // 浏览器js交互
QString _htmlDir; // html文件夹路径
QString _indexFileName; // html文件
QLabel *_pLabelCenterUp; // 显示文字的控件
QLabel *_pLabelCenterDown; // 显示百分比的控件
QString _initJsStr; // 初始化的js字符串
QString _initValueJsStr; // 设置值的js字符串
private:
double _percent; // 百分比(0~100)
};
#endif // PIEECHARTWIDGET_H
PieEChartWidget.cpp
#include "PieEChartWidget.h"
#include "ui_PieEChartWidget.h"
#include <QFile>
#include <QMessageBox>
#include <QTimer>
// QtCreator在msvc下设置编码也或有一些乱码,直接一刀切,避免繁琐的设置
//#define MSVC
#ifdef MSVC
#define QSTRING(s) QString::fromLocal8Bit(s)
#else
#define QSTRING(s) QString(s)
#endif
#include <QDebug>
#include <QDateTime>
//#define LOG qDebug()<<__FILE__<<__LINE__
//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__
//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()
//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")
#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")
PieEChartWidget::PieEChartWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::PieEChartWidget),
_pWebEngineView(0),
_pWebEnginePage(0),
_pWebChannel(0),
_htmlDir("D:/qtProject/echartsDemo/echartsDemo/modules/PieEChartWidget/html"), // 使用了绝对路径,引到html文件夹
_indexFileName("PieEChartWidget.html"),
_pLabelCenterUp(0),
_pLabelCenterDown(0)
{
ui->setupUi(this);
QString version = "v1.0.0";
setWindowTitle(QString("基于Qt的EChartb饼状图Demo %1(长沙红胖子Qt").arg(version));
// 设置无边框,以及背景透明
// 背景透明,在界面构架时,若为本窗口为其他窗口提升为本窗口时,
// 则再qss会在主窗口第一级添加frame_all,防止其他窗口提升本窗口而冲掉qss设置
// setWindowFlag(Qt::FramelessWindowHint);
// setAttribute(Qt::WA_TranslucentBackground, true);
#if 0
// 这是方法一:让滚动条不出来(通过大小),还有一个方法是在html设置body的overflow: hidden
// resize(600 + 20, 400 + 20);
#endif
initControl();
}
PieEChartWidget::~PieEChartWidget()
{
delete ui;
}
void PieEChartWidget::setPercent(double percent)
{
if(percent < 0 || percent > 100)
{
return;
}
LOG << percent;
if(percent == 100)
{
_pLabelCenterDown->setText(QSTRING("100%"));
}else{
if(_percent < 10)
{
_pLabelCenterDown->setText(QSTRING("%1%").arg(percent, 0, 'g', 2));
}else{
_pLabelCenterDown->setText(QSTRING(" %1%").arg(percent, 0, 'g', 2));
}
}
QString jsStr = QSTRING(
"option.series[0].data[0].value = %1;"
"option.series[0].data[1].value = %2;"
"myChart.setOption(option, true);")
.arg(percent)
.arg(100 - percent);
LOG << jsStr;
_percent = percent;
runJsScript(jsStr);
}
void PieEChartWidget::initControl()
{
_pLabelCenterUp = new QLabel(this);
_pLabelCenterUp->raise();
_pLabelCenterUp->setAlignment(Qt::AlignBottom | Qt::AlignHCenter);
_pLabelCenterUp->setText(QSTRING("开机率"));
_pLabelCenterUp->setStyleSheet("font-size: 36px;"
"font-weight: bold;"
"align: top ;"
"color: rgb(41, 235, 255);"
"padding: 0 30 10 0;");
_pLabelCenterDown = new QLabel(this);
_pLabelCenterDown->raise();
_pLabelCenterDown->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
_pLabelCenterDown->setText(QSTRING("%1%").arg(0));
_pLabelCenterDown->setStyleSheet("font-size: 64px;"
"font-weight: bold;"
"align: center;"
"color: rgb(41, 235, 255);"
"padding: 0 30 0 0;");
_pWebEngineView = new QWebEngineView(this);
_pWebEnginePage = new QWebEnginePage(this);
_pWebChannel = new QWebChannel(this);
QString filePath;
#if 0
// 使用绝对路径
filePath = QString("%1/%2").arg(_htmlDir).arg(_indexFileName);
#else
// 使用资源路径
filePath = "qrc:/pieEChartWidget/html/eChartWidget.html";
#endif
LOG << "file exist:" << QFile::exists(filePath) << filePath;
#if 0
// 打印html文件内容
QFile file(_indexFilePath);
file.open(QIODevice::ReadOnly);
LOG << QString(file.readAll());
file.close();
#endif
connect(_pWebEnginePage, SIGNAL(loadFinished(bool)), this, SLOT(slot_loadFinished(bool)));
_pWebEnginePage->load(QUrl(filePath));
_pWebEnginePage->setWebChannel(_pWebChannel);
_pWebEngineView->setPage(_pWebEnginePage);
// 背景透明
// _pWebEngineView->setStyleSheet("background-color: transparent");
_pWebEnginePage->setBackgroundColor(Qt::transparent);
// 鼠标穿透
_pWebEngineView->setAttribute(Qt::WA_TransparentForMouseEvents, true);
}
void PieEChartWidget::slot_loadFinished(bool result)
{
if(result)
{
initJs();
resizeEvent(0);
}
}
void PieEChartWidget::initJs()
{
_initJsStr = QSTRING(
"var option;"
"option = {"
" legend: {"
" top: '90%',"
" show: false"
" },"
" series: ["
" {"
" selectedMode: 'single', /* 选择模式 */"
" selectedOffset: 0, /* 选取后偏移,需要先设置选择模式才生效 */"
" type: 'pie', /* 图例类型 */"
" radius: ['60%', '90%'], /* 同心圆双边界区域 */"
" itemStyle: { /* 数据项样式 */"
" borderRadius: 0, /* 边界圆角 */"
" borderColor: '#FF0000', /* 边界颜色 */"
" borderWidth: 0 /* 边界宽度 */"
" },"
" avoidLabelOverlap: true,"
" label: {"
" show: false,"
" fontSize: '32',"
" fontWeight: 'bold',"
" formatter: '{b}\\n\\n{d}%',"
" position: 'center'"
" },"
" emphasis: { /* 高亮状态的扇区和标签样式 */"
" label: {"
" show: false,"
" fontSize: '32',"
" fontWeight: 'bold'"
" }"
" },"
" labelLine: {"
" show: false"
" },"
" data: ["
" {"
" value: 0,"
" name: '开机率',"
" selected: true,"
" itemStyle: {"
" color: 'rgba(41, 235, 255, 255)',"
" shadowColor:'rgba(41, 235, 255, 255)',"
" shadowBlur: 10,"
" shadowOffsetX: 0,"
" shadowOffsetY: 0,"
" }"
" },"
" {"
" value: 100,"
" name: '11',"
" itemStyle: {"
" color: 'rgba(45,62,113,255)',"
" shadowColor:'rgba(45,62,113,255)',"
" shadowBlur: 10,"
" shadowOffsetX: 0,"
" shadowOffsetY: 0,"
" }"
" }"
" ]"
" }"
" ]"
"};"
"myChart.setOption(option);"
);
{
_initValueJsStr = QSTRING(
"var option;"
"option = {"
" legend: {"
" top: '90%',"
" show: false"
" },"
" series: ["
" {"
" selectedMode: 'single', /* 选择模式 */"
" selectedOffset: 0, /* 选取后偏移,需要先设置选择模式才生效 */"
" type: 'pie', /* 图例类型 */"
" radius: ['60%', '90%'], /* 同心圆双边界区域 */"
" itemStyle: { /* 数据项样式 */"
" borderRadius: 0, /* 边界圆角 */"
" borderColor: '#FF0000', /* 边界颜色 */"
" borderWidth: 0 /* 边界宽度 */"
" },"
" avoidLabelOverlap: true,"
" label: {"
" show: false,"
" fontSize: '32',"
" fontWeight: 'bold',"
" formatter: '{b}\\n\\n{d}%',"
" position: 'center'"
" },"
" emphasis: { /* 高亮状态的扇区和标签样式 */"
" label: {"
" show: false,"
" fontSize: '32',"
" fontWeight: 'bold'"
" }"
" },"
" labelLine: {"
" show: false"
" },"
" data: ["
" {"
" value: %1,"
" name: '开机率',"
" selected: true,"
" itemStyle: {"
" color: 'rgba(41, 235, 255, 255)',"
" shadowColor:'rgba(41, 235, 255, 255)',"
" shadowBlur: 10,"
" shadowOffsetX: 0,"
" shadowOffsetY: 0,"
" }"
" },"
" {"
" value: %2,"
" name: '',"
" itemStyle: {"
" color: 'rgba(45, 62, 113, 255)',"
" shadowColor:'rgba(45,62,113,255)',"
" shadowBlur: 10,"
" shadowOffsetX: 0,"
" shadowOffsetY: 0,"
" }"
" }"
" ]"
" }"
" ]"
"};"
"myChart.setOption(option);"
);
}
setPercent(0);
runJsScript(_initJsStr);
}
void PieEChartWidget::runJsScript(QString str)
{
if(_pWebEnginePage)
{
_pWebEnginePage->runJavaScript(str);
}
}
void PieEChartWidget::resizeEvent(QResizeEvent *event)
{
if(_pWebEngineView)
{
_pWebEngineView->setGeometry(ui->label_echarts->geometry());
}
if(_pLabelCenterUp)
{
QRect echarRect = ui->label_echarts->geometry();
_pLabelCenterUp->setGeometry(echarRect.x(),
echarRect.y(),
echarRect.width(),
echarRect.height()/2);
}
if(_pLabelCenterDown)
{
QRect echarRect = ui->label_echarts->geometry();
_pLabelCenterDown->setGeometry(echarRect.x(),
echarRect.y() + echarRect.height()/2,
echarRect.width(),
echarRect.height()/2);
}
}
void PieEChartWidget::on_pushButton_clear_clicked()
{
setPercent(0.0f);
}
void PieEChartWidget::on_pushButton_flush_clicked()
{
QString jsStr =
"var empty = {};"
"myChart.setOption(empty, true);"
"myChart.setOption(option, true);";
runJsScript(jsStr);
}
void PieEChartWidget::on_pushButton_createRandom_clicked()
{
float value = qrand() % 10001 / 100;
setPercent(value);
}
void PieEChartWidget::on_pushButton_reset_clicked()
{
initJs();
}
void PieEChartWidget::on_doubleSpinBox_valueChanged(double arg1)
{
setPercent(ui->doubleSpinBox->value());
}
工程模板v1.3.0
入坑
入坑一:js出现错误“unexpected token”
问题
原理
判断传入编码转换或者语法规则有问题
解决方法
从字符串这种方式,只能使用/**/,如下图:
入坑二:出现Invalid or unexpected token错误
问题
原理
判断输入在定义label格式的时候,输入了特殊字符,导致整条字符串没有达到预期转义
解决方法
发现打印出来是对的也不行,主要是给换行符加上,换行符qt的直接换行展示为\n,到浏览器那边估计是直接换行了,导致不在一行了。
改掉即可,给\n改成\n,建议可打印出来看一看即可。
入坑三:嵌入Qt中的显示不对
问题
原理
重新一条一条递增添加js语句找到问题为样式部分的问题。
解决
rgba改a即可,这是之前测试过rgba,rgba中的a是有效果的。
入坑四:Qt中实际饼图的默认Label显示不对
问题
Label显示不对
原理
版本相关,但qt无法嵌入echart5无法显示(具体原因查看本系列第一篇)。
其他尝试
最起码笔者使用的这个版本是有问题的。
直接加载js文件,也是如此:
解决
绕开,用QLabel显示混合显示。
Qt+ECharts开发笔记(四):ECharts的饼图介绍、基础使用和Qt封装百分比图Demo的更多相关文章
- Django开发笔记四
Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.邮箱激活 users app下,models.py: ...
- Qt+ECharts开发笔记(三):ECharts的柱状图介绍、基础使用和Qt封装Demo
前言 上一篇成功是EChart随着Qt窗口变化而变化,本篇将开始正式介绍柱状图介绍.基础使用,并将其封装一层Qt. 本篇的demo实现了隐藏js代码的方式,实现了一个条形图的基本交互方式,即Qt ...
- Qt+ECharts开发笔记(二):Qt窗口动态调整大小,使ECharts跟随Qt窗口大小变换而变换大小
前言 上一篇将ECharts嵌入Qt中,在开始ECharts使用之前,还有一个很重要的功能,就是在窗口变换大小的时候,ECharts的图表尺寸也要跟随Qt窗口变换大小而变换大小. Demo演示 ...
- Qt+ECharts开发笔记(五):ECharts的动态排序柱状图介绍、基础使用和Qt封装Demo
前言 上一篇的demo使用隐藏js代码的方式,实现了一个饼图的基本交互方式,并预留了Qt模块对外的基础接口. 本篇的demo实现了自动排序的柱状图,实现了一个自动排序柱状图的基本交互方式,即Qt ...
- TERSUS无代码开发(笔记01)-按装下载和基础语法
1.中国官网 https://tersus.cn/ 2.下载:https://tersus.cn/download/ 3.开发文档:https://tersus.cn/docs/ 4.基本元件说明 图 ...
- echarts使用笔记四:双Y轴
1.双Y轴显示数量和占比 app.title = '坐标轴刻度与标签对齐'; option = { title : { //标题 x : 'center', y : 5, text : '数量和占比图 ...
- ECharts学习总结(四):echarts的实例方法
echarts的实例方法非常重要,因为在实际运用中我们额图表的数据不可能是死的,而是动态变化的,实例方法为动态改变数据提供了方法.故特意从官网上面把下面实例方法进行记录: 注:下面内容摘自echart ...
- 麒麟系统开发笔记(二):国产麒麟系统搭建Qt开发环境安装Qt5.12
前言 开发国产应用,使用到银河麒麟V4,V10,本篇以V10记录,参照上一篇可安装V4.V7.V10三个版本,麒麟V4系自带了Qt,麒麟V10没有自带Qt,需要自己编译搭建环境. 银河麒麟V1 ...
- echarts使用笔记五:echarts的Zoom控件
option = { title: { text: '趋势' }, tooltip : { trigger: 'axis', show:true, axisPointer : { // 坐标轴指示器, ...
随机推荐
- drools执行完某个规则后终止别的规则执行
目录 1.背景 2.需求 3.实现方案 1.通过Fact判断 2.通过全局变量判断 3.通过halt方法 4.实现上述需求 4.1 drl 文件编写 4.2 运行结果 5.完整代码 1.背景 在我们开 ...
- 【Azure Developer】App Service + PubSub +JS 实现多人版黑客帝国文字流效果图
需要描述 1)实现黑客帝国文字流效果图,JS功能 2)部署在云中,让大家都可以访问,App Service实现 3)大家都能发送消息,并显示在文字流中,PubSub(websocket)实现 终极效果 ...
- 2006NOIP普及组:明明的随机数
明明的随机数 时间限制:1000ms 内存限制:65536KB 题目描述: 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数 ...
- String 为什么不可变?
转载来源:String为什么不可变 今天来分享一道群友去阿里云面试遇到的 Java 基础面试真题:"String.StringBuffer.StringBuilder 的区别?String ...
- GitHub 简介
用详细的图文对GitHub进行简单的介绍. git是一个版本控制工具,github是一个用git做版本控制的项目托管平台. 主页介绍: overview:总览.相当于个人主页. repositorie ...
- MySQL数据库4
内容概要 查询关键字 查询关键字之having过滤 查询关键字之distinct去重 查询关键字之order by排序 查询关键字之limit分页 查询关键字之regexp正则 多表查询思路 可视化软 ...
- SAP BPC 开发日记
1.获取维度模型的方法1 DATA:i_appset_id TYPE uj_appset_id, i_appl_id TYPE uj_appl_id.i_appset_id = 'SINO ...
- 获取mybatis注解方式新增数据时非自增插入的主键
场景:插入数据的时候,获取不到非自增的主键.原因:对象中没有主键的值,插入后主键才有值. 解决方案:使用 @SelectKey @SelectKey中: statement是要运行的SQL语句,即查询 ...
- zabbix主动式和被动式
推荐: zabbix我们使用主动式,主动式的话,可以把压力都分散到agent上,压力小. 1: zabbix主动式和被动式是相对于agent来说的. zabbix server去获取zabbix ag ...
- 数组基础篇(对应C++ Primer plus 4.10)
概要:数组是由一组同类型的元素组成的集合,在内存上是一片连续的存储空间.C++提供了三种数组的表示方法:普通数组,模板类vector(C++98 新增的标准模板库STL提供该模板类)和模板类array ...