前言

  前一篇介绍了横向柱图图。本篇将介绍基础饼图使用,并将其封装一层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的更多相关文章

  1. Django开发笔记四

    Django开发笔记一 Django开发笔记二 Django开发笔记三 Django开发笔记四 Django开发笔记五 Django开发笔记六 1.邮箱激活 users app下,models.py: ...

  2. Qt+ECharts开发笔记(三):ECharts的柱状图介绍、基础使用和Qt封装Demo

    前言   上一篇成功是EChart随着Qt窗口变化而变化,本篇将开始正式介绍柱状图介绍.基础使用,并将其封装一层Qt.  本篇的demo实现了隐藏js代码的方式,实现了一个条形图的基本交互方式,即Qt ...

  3. Qt+ECharts开发笔记(二):Qt窗口动态调整大小,使ECharts跟随Qt窗口大小变换而变换大小

    前言   上一篇将ECharts嵌入Qt中,在开始ECharts使用之前,还有一个很重要的功能,就是在窗口变换大小的时候,ECharts的图表尺寸也要跟随Qt窗口变换大小而变换大小.   Demo演示 ...

  4. Qt+ECharts开发笔记(五):ECharts的动态排序柱状图介绍、基础使用和Qt封装Demo

    前言   上一篇的demo使用隐藏js代码的方式,实现了一个饼图的基本交互方式,并预留了Qt模块对外的基础接口.  本篇的demo实现了自动排序的柱状图,实现了一个自动排序柱状图的基本交互方式,即Qt ...

  5. TERSUS无代码开发(笔记01)-按装下载和基础语法

    1.中国官网 https://tersus.cn/ 2.下载:https://tersus.cn/download/ 3.开发文档:https://tersus.cn/docs/ 4.基本元件说明 图 ...

  6. echarts使用笔记四:双Y轴

    1.双Y轴显示数量和占比 app.title = '坐标轴刻度与标签对齐'; option = { title : { //标题 x : 'center', y : 5, text : '数量和占比图 ...

  7. ECharts学习总结(四):echarts的实例方法

    echarts的实例方法非常重要,因为在实际运用中我们额图表的数据不可能是死的,而是动态变化的,实例方法为动态改变数据提供了方法.故特意从官网上面把下面实例方法进行记录: 注:下面内容摘自echart ...

  8. 麒麟系统开发笔记(二):国产麒麟系统搭建Qt开发环境安装Qt5.12

    前言   开发国产应用,使用到银河麒麟V4,V10,本篇以V10记录,参照上一篇可安装V4.V7.V10三个版本,麒麟V4系自带了Qt,麒麟V10没有自带Qt,需要自己编译搭建环境.   银河麒麟V1 ...

  9. echarts使用笔记五:echarts的Zoom控件

    option = { title: { text: '趋势' }, tooltip : { trigger: 'axis', show:true, axisPointer : { // 坐标轴指示器, ...

随机推荐

  1. BI 如何让SaaS产品具有 “安全感”和“敏锐感”(上)

    SaaS模式一经推出,凭借自身的高性价比.低维护成本,无需软硬件维护.无需运维等明晃晃的优点,得到了爆发式的增长,甚至全面改变了软件的开发模式.各位老总的问候语,不知从什么时候开始,都变成了:&quo ...

  2. Tmux常用命令总结

    会话 # 创建会话 tmux new -s work -s是session # 查看tmux进程 ps aux | grep tmux # 连接会话 tmux attach -t work # 会话分 ...

  3. pycharm解释器的配置等

    转自:http://www.360doc.com/content/18/0913/14/11881101_786350505.shtml 为什么安装python后,还需要pycharm配置环境 我们实 ...

  4. 3D还原货拉拉女孩身亡真相,这一环值得反思!

    货拉拉女孩跳车身亡的消息,让人惋惜又震惊.司机多次偏离原始路线,女孩最终选择跳车,结果不幸身亡. 货拉拉女孩跳车真相被3D还原 有人质疑平台监管不力,造成如此惨剧,有人吐槽企业压榨员工,司机绕路是不得 ...

  5. 利用XtraDiagram.DiagramControl进行流程图形的绘制和控制

    DevExpress提供了一个比较强大的图形绘制工具,可以用于绘制各种图形,如流程图.组织机构图等等,本篇随笔介绍XtraDiagram.DiagramControl的使用,以及利用代码对其属性进行控 ...

  6. python基础知识-day9(数据驱动)

    1.数据驱动的概念 在自动化测试中,需要把测试的数据分离到JSON,YAML等文件中. 2.YAML 的相关知识 YAML 入门教程 分类 编程技术 YAML 是 "YAML Ain't a ...

  7. c# 把网络图片http://....png 打包成zip文件

    思路: 1.把网络图片下载到服务器本地. 2.读取服务器图片的文件流 3.使用zip帮助类,把图片文件流写进zip文件流. 4.如果是文件服务器,把zip文件流 推送文件服务器,生成zip的下载url ...

  8. CMU15445 (Fall 2019) 之 Project#3 - Query Execution 详解

    前言 经过前面两个实验的铺垫,终于到了给数据库系统添加执行查询计划功能的时候了.给定一条 SQL 语句,我们可以将其中的操作符组织为一棵树,树中的每一个父节点都能从子节点获取 tuple 并处理成操作 ...

  9. 【摸鱼神器】UI库秒变低代码工具——表单篇(二)子控件

    上一篇介绍了表单控件,这一篇介绍一下表单里面的各种子控件的封装方式. 主要内容 需求分析 子控件的分类 子控件属性的分类 定义 interface. 定义子控件的的 props. 定义 json 文件 ...

  10. day03 对象流与序列化

    对象流 java.io.ObjectOutputStream和ObjectInputSteam 对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化. 对象序列化:将一个java对象按照其 ...