...
第一步:
定义图表所需数据结构xxxDataConfig,继承抽象类AbstractDataConfig。
eg :
声明变量x、y、z(保存配置的xyz轴数据的字段名称)。
实现抽象方法:readXML(模板读取)&& writeXML(模板写入)&& clone && equals && hashCode && dataSetFields(返回由声明的变量组成的数组,用于预览时取数据库取数)。
其中,供开发者使用的readExtendedField&writeExtendedField方法的第二个参数是字段写入模板对应的key。
Code Block |
---|
title | DemoDataConfig |
---|
collapse | true |
---|
|
package com.fr.plugin.demo;
import com.fr.extended.chart.AbstractDataConfig;
import com.fr.extended.chart.ExtendedField;
import com.fr.general.ComparatorUtils;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLableReader;
/**
* Created by shine on 2018/3/24.
*/
public class DemoDataConfig extends AbstractDataConfig {
private ExtendedField x = new ExtendedField();
private ExtendedField y = new ExtendedField();
private ExtendedField z = new ExtendedField();
public ExtendedField getX() {
return x;
}
public void setX(ExtendedField x) {
this.x = x;
}
public ExtendedField getYcss文件。
xxxChart重写requiredCSS.
Code Block |
---|
|
@Override
protected String[] requiredCSS() {
return new String[] {
"com/fr/plugin/demo/demo.css"
};
} |
超链。
首先:实现前期准备中第三步中后台图表xxxChart的抽象方法 hyperLinkParas。
Code Block |
---|
|
private static final HyperLinkPara X = new HyperLinkPara() {
@Override
public String getName() {
return "X轴";
}
@Override
public String getFormulaContent() {
return "X";
}
@Override
public String[] getProps() {
return new String[]{"data", "0"};
}
};
private static final HyperLinkPara Y = new HyperLinkPara() {
@Override
public String getName() {
return "Y轴";
}
@Override
public String getFormulaContent() {
return "Y";
}
@Override
public String[] getProps() {
return new String[]{"data", "1"};
}
};
private static final HyperLinkPara[] PARAS = new HyperLinkPara[]{
X,
Y
};
protected HyperLinkPara[] hyperLinkParas() {
return PARAS;
} |
其次:重写前期准备第五步中 图表界面插件接口xxxUI中的方法getAttrPaneArray
Code Block |
---|
|
@Override
public AbstractChartAttrPane[] getAttrPaneArray(AttributeChangeListener listener) {
return new AbstractChartAttrPane[]{
new ExtendedOtherPane()
};
} |
最后:在前期准备第二步写的前端图表对象xxxWrapper中的初始方法_init中 绑定事件处理函数getLinkFun。ps:这边是echarts的定义事件接口,不同前端库实现不同。比如fr自带vancharts是option.onClick = this.getLinkFun();
Code Block |
---|
|
_init: function (dom, option) {
var chart = echarts.init(dom);
//绑定点击触发超链函数
chart.on('click', this.getLinkFun());
chart.setOption(option);
return chart;
}, |
自动刷新。
首先:在前期准备第二步写的前端图表对象xxxWrapper中添加方法_refresh。方法体 调用所用图表库的刷新图表接口。
Code Block |
---|
|
_refresh: function (chart, option) {
chart.setOption(option);
}, |
其次:和超链中的其次一样。
重写前期准备第五步中 图表界面插件接口xxxUI中的方法getAttrPaneArray
Code Block |
---|
|
@Override
public AbstractChartAttrPane[] getAttrPaneArray(AttributeChangeListener listener) {
return new AbstractChartAttrPane[]{
new ExtendedOtherPane()
};
} |
更多样式配置。
大小颜色标题图例等等。栗子:标题。注意:添加属性需要完善read&&write&clone&equals&populate&update,缺一不可。
首先:在前期准备中第三步中xxxChart中添加属性stringTitle & 重写readAttr和writeAttr方法&clone&equals&addJSON添加到前台option中。如果添加的属性不是基本数据类型,需要重写方法readXML&writeXML。
Code Block |
---|
|
private StringFormula titleFormula = new StringFormula();
public StringFormula getTitleFormula() {
return titleFormula;
}
public void setTitleFormula(StringFormula titleFormula) {
this.titleFormula = titleFormula;
}
@Override
protected void readAttr(XMLableReader reader) {
super.readAttr(reader);
this.getTitleFormula().readAttr("title", reader);
}
@Override
protected void writeAttr(XMLPrintWriter writer) {
super.writeAttr(writer);
this.getTitleFormula().writeAttr("title", writer);
}
@Override
public Object clone() throws CloneNotSupportedException {
DemoChart result = (DemoChart) super.clone();
if (getTitleFormula() != null) {
result.setTitleFormula(this.getTitleFormula().clone());
}
return result;
}
@Override
public int hashCode() {
return super.hashCode() + AssistUtils.hashCode(this.getTitleFormula());
}
@Override
public boolean equals(Object ob) {
return super.equals(ob)
&& ob instanceof DemoChart
&& AssistUtils.equals(this.getTitleFormula(), ((DemoChart) ob).getTitleFormula())
;
}
@ExecuteFunctionRecord
@Override
protected void addJSON(DemoDataConfig dataConfig, JSONObject jsonObject, Repository repo, JSONPara para) throws JSONException {
jsonObject.put("title", JSONFactory.createJSON(JSON.OBJECT).put("text", getTitleFormula().getResult()));
}
|
其次:定义标题面板xxxTitlePane。继承类ExtendedScrollPane。实现方法 populateBean&updateBean&createContentPane&title4PopupWindow。注意:泛型DemoChart。
Code Block |
---|
title | DemoTitlePane |
---|
collapse | true |
---|
|
package com.fr.plugin.demo;
import com.fr.design.formula.TinyFormulaPane;
import com.fr.extended.chart.ExtendedScrollPane;
import javax.swing.JPanel;
import java.awt.BorderLayout;
/**
* Created by shine on 2018/3/25.
*/
public class DemoTitlePane extends ExtendedScrollPane<DemoChart>{
private TinyFormulaPane title;
@Override
public void populateBean(DemoChart ob) {
title.populateBean(ob.getTitleFormula().getContent());
}
@Override
public void updateBean(DemoChart ob) {
ob.getTitleFormula().setContent(title.updateBean());
}
@Override
protected JPanel createContentPane() {
JPanel panel = new JPanel(new BorderLayout());
title = new TinyFormulaPane();
panel.add(title, BorderLayout.CENTER);
return panel;
}
@Override
protected String title4PopupWindow() {
return "标题";
}
} |
再次:定义样式面板xxxStylePane。实现抽象方法initPaneList(返回样式配置面板数组)。
Code Block |
---|
title | DemoStylePane |
---|
collapse | true |
---|
|
package com.fr.plugin.demo;
import com.fr.extended.chart.AbstractExtendedStylePane;
import com.fr.extended.chart.ExtendedScrollPane;
import java.util.ArrayList;
import java.util.List;
/**
* Created by shine on 2018/3/25.
*/
public class DemoStylePane extends AbstractExtendedStylePane<DemoChart>{
@Override
protected List<ExtendedScrollPane<DemoChart>> initPaneList() {
List<ExtendedScrollPane<DemoChart>> list = new ArrayList<ExtendedScrollPane<DemoChart>>();
list.add(new DemoTitlePane());
return list;
}
} |
最后:重写前期准备第五步中 图表界面插件接口xxxUI中的方法getAttrPaneArray
Code Block |
---|
|
@Override
public AbstractChartAttrPane[] getAttrPaneArray(AttributeChangeListener listener) {
return new AbstractChartAttrPane[]{
new DemoStylePane()
};
} |
联动&公式。
因为上一步骤配置标题的已经写好。要想标题可以使用公式。只需要实现前期准备中第三步中xxxChart的抽象方法 formulas。返回所有需要处理的公式属性集合。
Code Block |
---|
|
@Override
protected List<StringFormula> formulas() {
List<StringFormula> list = new ArrayList<StringFormula>();
list.add(this.getTitleFormula());
return list;
} |
导出。
实现前期准备中第三步中xxxChart的抽象方法 createExportProcessor
说明:
使用webgl flash等phantomjs不支持的前端库,只能使用web端导出用前端图表库导出接口。返回new JSExportProcessor()。
非webgl等,即可使用phantomjs导出,也可使用前端库的导出接口。返回new PhantomExportProcessor() 或者 new JSExportProcessor()。
Code Block |
---|
protected ExportProcessor createExportProcessor() {
return new JSExportProcessor();
} |
ps:如果返回的是JSExportProcessor,必须:需要在前期准备第二步写的前端图表对象xxxWrapper中添加方法_exportImage,调用所用图表库的导出图片接口;_exportInit,图表初始接口+导出特殊处理,这个可以不加,不加的情况使用_init
Code Block |
---|
|
_exportInit:function (dom, option) {
option.animation = false;
return this._init(dom, option);
},
_exportImage: function (chart) {
return chart.getConnectedDataURL({type: 'png'})
} |
ps:如果选择的是PhantomExportProcessor,可选:这时候如果你希望设计器展示的图表不仅仅是一张固定的图片,设置的样式属性(除了数据配置,我们暂时称其他属性为样式属性)可以随着你的配置实时改变,你可以重写前期准备第三步后台图表对象xxxChart中的designerDataConfig方法(固定数据配置)。
Code Block |
---|
|
@Override
protected DemoDataConfig designerDataConfig() {
DemoDataConfig demoDataConfig = new DemoDataConfig();
demoDataConfig.setX(new ExtendedField("days", new String[]{"Monday","Tuesday"}));
demoDataConfig.setY(new ExtendedField("name", new String[]{"Lily", "Marks"}));
demoDataConfig.setZ(new ExtendedField("money", new String[]{"100", "200"}));
return super.designerDataConfig();
} |
国际化
类型界面加一个图标。
首先,定义xxxTypePane,继承ExtendedTypePane。重写 getTypeIconPath(图标路径)&& getTypeTipName(tooltip)方法。
Code Block |
---|
title | DemoTypePane |
---|
collapse | true |
---|
|
package com.fr.plugin.demo;
import com.fr.extended.chart.ExtendedTypePane;
/**
* Created by shine on 2018/4/19.
*/
public class DemoTypePane extends ExtendedTypePane {
@Override
protected String[] getTypeIconPath() {
return new String[]{
"com/fr/plugin/demo/icon.png"
};
}
@Override
protected String[] getTypeTipName() {
return new String[]{
"demo tooltip"
};
}
}
|
其次,重写前期准备第五步中 图表界面插件接口xxxUI中的方法getPlotTypePane.返回上面的xxxTypePane。
Code Block |
---|
|
@Override
public AbstractChartTypePane getPlotTypePane() {
return new DemoTypePane();
} |
类型界面添加多种详细类型。
首先,定义枚举类型yyyType。
Code Block |
---|
title | ThemeType |
---|
collapse | true |
---|
|
package com.fr.plugin.demo;
/**
* Created by shine on 2018/4/19.
*/
public enum ThemeType {
DARK,
WHITE;
public static ThemeType parseInt(int index) {
for (ThemeType type : ThemeType.values()) {
if (type.ordinal() == index) {
return type;
}
}
return DARK;
}
}
|
其次,类似此页面中的3更多样式配置中属性的添加,在前期准备中第三步中xxxChart中添加属性themeType & 重写readAttr和writeAttr方法&clone&equals&addJSON添加到前台option中。
Code Block |
---|
|
private ThemeType themeType = ThemeType.DARK;
public ThemeType getThemeType() {
return themeType;
}
public void setThemeType(ThemeType themeType) {
this.themeType = themeType;
}
@Override
protected void readAttr(XMLableReader reader) {
super.readAttr(reader);
this.setThemeType(ThemeType.parseInt(reader.getAttrAsInt("theme", 0)));
this.getTitleFormula().readAttr("title", reader);
}
@Override
protected void writeAttr(XMLPrintWriter writer) {
super.writeAttr(writer);
writer.attr("theme", getThemeType().ordinal());
this.getTitleFormula().writeAttr("title", writer);
}
@Override
public Object clone() throws CloneNotSupportedException {
DemoChart result = (DemoChart) super.clone();
if (getTitleFormula() != null) {
result.setTitleFormula(this.getTitleFormula().clone());
}
result.setThemeType(this.getThemeType());
return result;
}
@Override
public int hashCode() {
return super.hashCode() + AssistUtils.hashCode(this.getTitleFormula(), this.getThemeType());
}
@Override
public boolean equals(Object ob) {
return super.equals(ob)
&& ob instanceof DemoChart
&& AssistUtils.equals(this.getTitleFormula(), ((DemoChart) ob).getTitleFormula())
&& AssistUtils.equals(this.getThemeType(), ((DemoChart) ob).getThemeType())
;
}
@ExecuteFunctionRecord
@Override
protected void addJSON(DemoDataConfig dataConfig, JSONObject jsonObject, Repository repo) throws JSONException {
jsonObject.put("theme", getThemeType() == ThemeType.DARK ? "dark" : "sth whatever");
jsonObject.put("title", JSONFactory.createJSON(JSON.OBJECT).put("text", getTitleFormula().getResult()));
... 省略其它 |
最后,重写上一步骤xxxTypePane中的getTypeIndex && setType(界面到图表对象的一个存取映射)。注意:泛型DemoChart
Code Block |
---|
|
package com.fr.plugin.demo;
import com.fr.extended.chart.ExtendedTypePane;
/**
* Created by shine on 2018/4/19.
*/
public class DemoTypePane extends ExtendedTypePane<DemoChart>{
@Override
protected String[] getTypeIconPath() {
return new String[]{
"com/fr/plugin/demo/dark.png",
"com/fr/plugin/demo/white.png"
};
}
@Override
protected String[] getTypeTipName() {
return new String[]{
"深色主题",
"浅色主题"
};
}
@Override
protected int getTypeIndex(DemoChart chart) {
return chart.getThemeType().ordinal();
}
@Override
protected void setType(DemoChart chart, int index) {
chart.setThemeType(ThemeType.parseInt(index));
}
} |
类型界面添加 其他组件。
首先,在xxxChart里面添加属性 threeDimensional。重写相关方法。
Code Block |
---|
|
private boolean threeDimensional = false;
public boolean isThreeDimensional() {
return threeDimensional;
}
public void setThreeDimensional(boolean threeDimensional) {
this.threeDimensional = threeDimensional;
}
@Override
protected void readAttr(XMLableReader reader) {
super.readAttr(reader);
this.setThemeType(ThemeType.parseInt(reader.getAttrAsInt("theme", 0)));
this.setThreeDimensional(reader.getAttrAsBoolean("threeD", false))
}
@Override
protected void writeAttr(XMLPrintWriter writer) {
super.writeAttr(writer);
writer.attr("theme", getThemeType().ordinal());
writer.attr("threeD", isThreeDimensional());
}
@Override
public Object clone() throws CloneNotSupportedException {
DemoChart result = (DemoChart) super.clone();
result.setThemeType(this.getThemeType());
result.setThreeDimensional(this.isThreeDimensional());
return result;
}
@Override
public int hashCode() {
return super.hashCode() + AssistUtils.hashCode(this.getTitleFormula(), this.getThemeType(), this.isThreeDimensional());
}
@Override
public boolean equals(Object ob) {
return super.equals(ob)
&& ob instanceof DemoChart
&& AssistUtils.equals(this.getThemeType(), ((DemoChart) ob).getThemeType())
&& AssistUtils.equals(this.isThreeDimensional(), ((DemoChart) ob).isThreeDimensional())
;
} |
其次,xxxTypePane中添加组件以及重写一些方法。
Code Block |
---|
|
private UIButtonGroup buttonGroup;
@Override
protected Component[][] getPaneComponents(JPanel typePane) {
buttonGroup = new UIButtonGroup(new String[]{"3d", "2d"});
return new Component[][]{
new Component[]{typePane},
new Component[]{buttonGroup}
};
}
@Override
protected void populate(DemoChart chart) {
super.populate(chart);
buttonGroup.setSelectedIndex(chart.isThreeDimensional() ? 0 : 1);
}
@Override
protected void update(DemoChart chart) {
super.update(chart);
chart.setThreeDimensional(buttonGroup.getSelectedIndex() == 0);
} |
没有数据面板。
DemoUI中getChartDataPane 返回null即可。当然,getTableDataSourcePane && getReportDataSourcePane 也无需定义了,可返回任意值。
Code Block |
---|
|
@Override
protected AbstractExtendedChartTableDataPane getTableDataSourcePane() {
return null;
}
@Override
protected AbstractReportDataContentPane getReportDataSourcePane() {
return null;
}
@Override
public ChartDataPane getChartDataPane(AttributeChangeListener listener) {
return null;
} |
数据面板 字段组件自定义(数据集数据不用下拉框&单元格数据不用公式输入框)。
首先,DemoDataConfig中添加自定义属性targetName,补充相应方法set&get&read&write&clone&hashcode&equals.
Code Block |
---|
|
private ExtendedField x = new ExtendedField();
private String targetName;
private ExtendedField y = new ExtendedField();
private ExtendedField z = new ExtendedField();
//省略其它。。。
public String getTargetName() {
return targetName;
}
public void setTargetName(String targetName) {
this.targetName = targetName;
}
@Override
protected void readAttr(XMLableReader reader) {
readExtendedField(x, "x", reader);
this.setTargetName(reader.getAttrAsString("targetName", ""));
readExtendedField(y, "y", reader);
readExtendedField(z, "z", reader);
}
@Override
protected void writeAttr(XMLPrintWriter writer) {
writeExtendedField(x, "x", writer);
writer.attr("targetName", this.getTargetName());
writeExtendedField(y, "y", writer);
writeExtendedField(z, "z", writer);
}
@Override
public ExtendedField[] dataSetFields() {
return new ExtendedField[]{
x,
y,
z
};
}
@Override
public DemoDataConfig clone() throws CloneNotSupportedException {
DemoDataConfig result = new DemoDataConfig();
result.setX(this.getX().clone());
result.setTargetName(this.getTargetName());
result.setY(this.getY().clone());
result.setZ(this.getZ().clone());
return result;
}
@Override
public int hashCode() {
return super.hashCode() + AssistUtils.hashCode(this.getX(), this.getY(), this.getZ(), this.getTargetName());
}
@Override
public boolean equals(Object obj) {
return obj instanceof DemoDataConfig
&& AssistUtils.equals(this.getX(), ((DemoDataConfig) obj).getX())
&& AssistUtils.equals(this.getTargetName(), ((DemoDataConfig) obj).getTargetName())
&& AssistUtils.equals(this.getY(), ((DemoDataConfig) obj).getY())
&& AssistUtils.equals(this.getZ(), ((DemoDataConfig) obj).getZ())
;
} |
其次,数据集数据源面板DemoTableDataPane中添加 private UITextField targetName; 补充相关方法fieldLabels&populate&update。重点:重写方法fieldComponents,按照界面组件顺序返回一个有序的组件数组。(单元格数据源面板同理)。
Code Block |
---|
|
private UIComboBox xComboBox;
private UITextField targetName;
private UIComboBox yComboBox;
private UIComboBox zComboBox;
@Override
protected String[] fieldLabels() {
return new String[]{
"X轴",
"指标名",
"Y轴",
"Z轴"
};
}
@Override
protected Component[] fieldComponents() {
return y;
}
if (xComboBox == null) {
public void setY(ExtendedField y) {
xComboBox = new UIComboBox();
this.y = y;
}
targetName public= ExtendedFieldnew getZUITextField();
{
return z;
yComboBox = }
new UIComboBox();
public void setZ(ExtendedField z) {
zComboBox = new UIComboBox();
this.z = z;
}
@Override
protectedreturn void readAttr(XMLableReader reader) new Component[]{
readExtendedField(x, "x", reader);
readExtendedField(y, "y", reader);xComboBox,
readExtendedField(z, "z", reader);
}
@OverridetargetName,
protected void writeAttr(XMLPrintWriter writer) {
writeExtendedField(xyComboBox, "x", writer);
writeExtendedField(y, "y", writer);
zComboBox
writeExtendedField(z, "z", writer) };
}
@Override
publicprotected ExtendedFieldUIComboBox[] dataSetFields() {
filedComboBoxes() {
if (xComboBox == null) {
xComboBox return= new ExtendedField[]{UIComboBox();
yComboBox = new x,
UIComboBox();
zComboBox = new UIComboBox();
y,
}
return new zUIComboBox[]{
};
}
@OverridexComboBox,
public DemoDataConfig clone() throws CloneNotSupportedException {
yComboBox,
DemoDataConfig result = new DemoDataConfig();
result.setX(this.getX().clone()); zComboBox
result.setY(this.getY().clone())};
}
result.setZ(this.getZ().clone());
@Override
protected void populate(DemoDataConfig dataConf) {
return result;
}
populateField(xComboBox, dataConf.getX());
@Override
public int hashCode targetName.setText(dataConf.getTargetName());
{
return super.hashCode() + AssistUtils.hashCode(this.getX(), this.getY(), thispopulateField(yComboBox, dataConf.getY());
populateField(zComboBox, dataConf.getZ());
}
@Override
public protected booleanDemoDataConfig equalsupdate(Object obj) {
return obj instanceof DemoDataConfig
dataConfig = new DemoDataConfig();
&& AssistUtils.equals(this.getX(), ((DemoDataConfig) obj)updateField(xComboBox, dataConfig.getX());
dataConfig.setTargetName(targetName.getText());
&& AssistUtils.equals(this.getY(), ((DemoDataConfig) obj)updateField(yComboBox, dataConfig.getY());
&& AssistUtils.equals(this.getZ(), ((DemoDataConfig) obj)updateField(zComboBox, dataConfig.getZ());
return dataConfig;
}
} |
第二步:
定义前台图表对象xxxWrapper.js,指定图表库的初始图表接口。
eg:demoWrapper最后,DemoChart的addJSON中将此属性根据前台接口加到json中。
Code Block |
---|
title | demoWrapper |
---|
collapse | true |
---|
|
demoWrapperprotected =void ExtendedChart.extend(addJSON(DemoDataConfig dataConfig, JSONObject jsonObject, Repository repo) throws JSONException {
//省略其它。。。。
_init:function (dom, option) {JSONArray array = JSONFactory.createJSON(JSON.ARRAY);
double maxValue = var chart = echarts.init(dom);Double.MIN_VALUE;
if (dataConfig != null) {
chart.setOption(option List<Object> xValues = dataConfig.getX().getValues();
List<Object> yValues return chart= dataConfig.getY().getValues();
}
}); |
第三步:
定义后台图表对象xxxChart,继承抽象类AbstractChart。注意点:继承的时候别忘了指定泛型DemoDataConfig,即extends AbstractChart<DemoDataConfig>。
eg:
实现抽象方法:getChartID (图表标志ID)&& getChartName(图表名称) && demoImagePath (图表选择界面图片路径) && addJSON (预览时生成的json对象,即图表展现所需配置项option && requiredJS (前端图表库js文件)&& wrapperName(前端图表对象,即第二步定义的对象名称)。
其中,获取某字段对应的数据库数据使用方法dataConfig.getXList<Object> zValues = dataConfig.getZ().getValues() |
)。 Code Block |
---|
title | DemoChart |
---|
collapse | true |
---|
|
package com.fr.plugin.extended.chart.demo;
import com.fr.base.BaseFormula;
import com.fr.extended.chart.AbstractChart;
import com.fr.extended.chart.HyperLinkPara;
import com.fr.extended.chart.export.ExportProcessor;
import com.fr.general.GeneralUtils;
import com.fr.json.JSON;
import com.fr.json.JSONArray;
import com.fr.json.JSONException;
import com.fr.json.JSONFactory;
import com.fr.json.JSONObject;
import com.fr.stable.web.Repository;
import java.util.List;
/**
* Created by shine on 2018/3/24.
*/
public class DemoChart extends AbstractChart<DemoDataConfig>{
private static final String ID = "DEMO_CHART";
private static final String NAME = "DEMO图表";
@Override
protected String getChartID() {
return ID;
}
@Override
public String getChartName;
//here
jsonObject.put("targetName", dataConfig.getTargetName());
for (int i = 0, len = xValues.size(); i < len; i++) {
maxValue = Math.max(GeneralUtils.objectToNumber(zValues.get(i)).doubleValue(), maxValue);
array.put(JSONFactory.createJSON(JSON.ARRAY).put(xValues.get(i)).put(yValues.get(i)).put(zValues.get(i)));
}
}
jsonObject.put("series", JSONFactory.createJSON(JSON.OBJECT).put("type", "bar3D").put("data", array)
.put("bevelSize", 0.2).put("bevelSmoothness", 2).put("shading", "color"));
//省略其它。。。。
} |
数据集数据源 对一些字段 公式汇总(求和 平均 最大 最小 等)。
首先,DemoDataConfig中添加两个字段属性expect actual,并添加响应get set 方法,补全read write datasetFields clone hashcode equals方法。
Code Block |
---|
|
//省略
private ExtendedField expect = new ExtendedField();
private ExtendedField actual = new ExtendedField();
public ExtendedField getExpect() {
return NAMEexpect;
}
@Override
public void protected String demoImagePath(setExpect(ExtendedField expect) {
this.expect return "com/fr/plugin/extended/chart/demo/demo.png"= expect;
}
@Override
protected void addJSON(DemoDataConfig dataConfig, JSONObject jsonObject, Repository repo, JSONPara para) throws JSONException {
public ExtendedField getActual() {
return actual;
}
JSONArraypublic arrayvoid = JSONFactory.createJSON(JSON.ARRAY);
setActual(ExtendedField actual) {
List<Object> xValuesthis.actual = dataConfig.getX().getValues()actual;
}
@Override
List<Object> yValuesprotected =void dataConfig.getY().getValues();readAttr(XMLableReader reader) {
List<Object> zValues = dataConfig.getZ().getValues(readExtendedField(x, "x", reader);
double maxValue = Double.MIN_VALUEthis.setTargetName(reader.getAttrAsString("targetName", ""));
for readExtendedField(int i = 0, len = xValues.size(); i < len; i++) {
y, "y", reader);
readExtendedField(z, "z", reader);
maxValue = Math.max(GeneralUtils.objectToNumber(zValues.get(i)).doubleValue(), maxValuereadExtendedField(expect, "expect", reader);
array.put(JSONFactory.createJSON(JSON.ARRAY).put(xValues.get(i)).put(yValues.get(i)).put(zValues.get(i))readExtendedField(actual, "actual", reader);
}
}@Override
protected void writeAttr(XMLPrintWriter writer) {
jsonObject.put("series", JSONFactory.createJSON(JSON.OBJECT).put("type", "bar3D").put("data", array)writeExtendedField(x, "x", writer);
.put("bevelSize", 0.2).put("bevelSmoothness", 2).put("shading", "color" writer.attr("targetName", this.getTargetName());
jsonObject.put("xAxis3D", JSONFactory.createJSON(JSON.OBJECT).put("type", "category"))writeExtendedField(y, "y", writer);
writeExtendedField(z, "z", writer);
.putwriteExtendedField(expect, "yAxis3Dexpect", JSONFactory.createJSON(JSON.OBJECT).put("type", "category"))writer);
writeExtendedField(actual, "actual", writer);
}
@Override
public ExtendedField[] dataSetFields() {
.put("zAxis3D", JSONFactory.createJSON(JSON.OBJECT).put("type", "value"));
return new ExtendedField[]{
jsonObject.put("grid3D", JSONFactory.createJSON(JSON.OBJECT).put("boxWidth", 200).put("boxDepth", 80));
jsonObject.put("visualMap", JSONFactory.createJSON(JSON.OBJECT)x,
.put("max", maxValue)y,
.put("color", JSONFactory.createJSON(JSON.ARRAY).put("#d94e5d").put("#eac736").put("#50a3ba")));
}
@Overridez,
expect,
actual
protected String[] requiredJS() {};
}
return new String[]{
@Override
public DemoDataConfig clone() throws CloneNotSupportedException {
DemoDataConfig result = "com/fr/plugin/extended/chart/demo/demoWrapper.js",new DemoDataConfig();
result.setX(this.getX().clone());
"com/fr/plugin/extended/chart/demo/echarts.js",result.setTargetName(this.getTargetName());
result.setY(this.getY().clone());
"com/fr/plugin/extended/chart/demo/echarts-gl.js"result.setZ(this.getZ().clone());
};
}
result.setExpect(this.getExpect().clone());
@Override
protected String wrapperName() {result.setActual(this.getActual().clone());
return "demoWrapper"result;
}
@Override
protectedpublic HyperLinkPara[]int hyperLinkParashashCode() {
return new HyperLinkPara[0];
}
super.hashCode() + AssistUtils.hashCode(this.getX(), this.getY(), this.getZ(),
@Override
protected List<StringFormula> formulas() {
this.getTargetName(), return nullthis.getExpect(), this.getActual());
}
@Override
protectedpublic ExportProcessorboolean createExportProcessorequals(Object obj) {
return null;
}
}
|
第四步:数据界面。
数据集数据界面xxxTableDataPane,继承抽象类AbstractExtendedChartTableDataPane。注意点:extends AbstractExtendedChartTableDataPane<DemoDataConfig>
eg:
声明变量下拉框 x、y、z。
实现抽象方法:fieldLabels (标签名称)&& filedComboBoxes (下拉框数组)&& populate (属性设置到界面组件)&& update(组件值保存到图表属性中)。
Code Block |
---|
title | DemoTableDataPane |
---|
collapse | true |
---|
|
package com.fr.plugin.extended.chart.demo;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.extended.chart.AbstractExtendedChartTableDataPane;
/**
* Created by shine on 2018/3/24.
*/
public class DemoTableDataPane extends AbstractExtendedChartTableDataPane<DemoDataConfig>{
private UIComboBox xComboBox;
private UIComboBox yComboBox;
private UIComboBox zComboBox;
@Override
protected String[] fieldLabels() {return obj instanceof DemoDataConfig
&& AssistUtils.equals(this.getX(), ((DemoDataConfig) obj).getX())
&& AssistUtils.equals(this.getTargetName(), ((DemoDataConfig) obj).getTargetName())
&& AssistUtils.equals(this.getY(), ((DemoDataConfig) obj).getY())
return new String[]{
&& AssistUtils.equals(this.getZ(), ((DemoDataConfig) obj).getZ())
"X轴",
&& AssistUtils.equals(this.getExpect(), "Y轴",
((DemoDataConfig) obj).getExpect())
&& AssistUtils.equals(this.getActual(), "Z轴"((DemoDataConfig) obj).getActual())
};
}
@Override;
protected UIComboBox[] filedComboBoxes() {
if (xComboBox == null) {
xComboBox = new UIComboBox();
yComboBox = new UIComboBox();
zComboBox = new UIComboBox()}
}
|
其次,DemoTableDataPane中声明下拉框组件expect&actual 补全方法labels componnets combobox populate update。
注意populate对应字段要调用populateFunctionField&update对应字段要调用updateFunctionField。
Code Block |
---|
|
package com.fr.plugin.demo;
import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.mainframe.chart.gui.data.CalculateComboBox;
import com.fr.extended.chart.AbstractExtendedChartTableDataPane;
import java.awt.Component;
/**
* Created by shine on 2018/3/24.
*/
public class DemoTableDataPane extends AbstractExtendedChartTableDataPane<DemoDataConfig>{
private UIComboBox xComboBox;
private UITextField }targetName;
return new UIComboBox[]{
private UIComboBox yComboBox;
private UIComboBox zComboBox;
private UIComboBox xComboBox,expect;
private CalculateComboBox expectFunction;
private UIComboBox actual;
yComboBox,
private CalculateComboBox actualFunction;
@Override
protected String[] fieldLabels() {
zComboBox
return };new String[]{
}
@Override
protected void populate(DemoDataConfig dataConf) { "X轴",
populateField(xComboBox, dataConf.getX());
populateField(yComboBox, dataConf.getY());"指标名",
populateField(zComboBox, dataConf.getZ());
}
@Override"Y轴",
protected DemoDataConfig update() {
DemoDataConfig"Z轴",
dataConfig = new DemoDataConfig();
updateField(xComboBox, dataConfig.getX());
"预期值",
updateField(yComboBox, dataConfig.getY());
updateField(zComboBox, dataConfig.getZ());
"预期汇总方式",
return dataConfig;
}
}
|
单元格配置界面xxxReportDataPane,继承抽象类AbstractExtendedChartReportDataPane。处理参考数据集数据配置界面,上栗子,不做累述。
Code Block |
---|
title | DemoReportDataPane |
---|
collapse | true |
---|
|
package com.fr.plugin.extended.chart.demo;
import com.fr.design.formula.TinyFormulaPane;
import com.fr.extended.chart.AbstractExtendedChartReportDataPane;
/**
* Created by shine on 2018/3/24.
*/
public class DemoReportDataPane extends AbstractExtendedChartReportDataPane<DemoDataConfig> {
private TinyFormulaPane xPane;
private TinyFormulaPane yPane "实际值",
"实际汇总方式"
};
private TinyFormulaPane zPane;}
@Override
protected StringComponent[] fieldLabelfieldComponents() {
return new String[] if (xComboBox == null) {
xComboBox = "X轴",new UIComboBox();
targetName = "Y轴",new UITextField();
yComboBox = "Z轴"new UIComboBox();
};
}
zComboBox = @Overridenew UIComboBox();
protected TinyFormulaPane[] formulaPanes() {
expect = ifnew UIComboBox(xPane == null) {);
xPaneexpectFunction = new TinyFormulaPaneCalculateComboBox();
yPaneactual = new TinyFormulaPaneUIComboBox();
zPaneactualFunction = new TinyFormulaPaneCalculateComboBox();
}
return new TinyFormulaPaneComponent[]{
xPanexComboBox,
yPanetargetName,
zPaneyComboBox,
};
}
@Override
protected void populate(DemoDataConfig dataConf) {zComboBox,
populateField(xPane, dataConf.getX());
expect,
populateField(yPane, dataConf.getY());
populateField(zPane, dataConf.getZ());
}
expectFunction,
@Override
protected DemoDataConfig update() {
actual,
DemoDataConfig dataConfig = new DemoDataConfig();
updateField(xPane, dataConfig.getX()); actualFunction
updateField(yPane, dataConfig.getY())};
}
updateField(zPane, dataConfig.getZ());
@Override
protected UIComboBox[] filedComboBoxes() {
return dataConfig;
}
}
|
第五步:
图表插件接口xxx,继承抽象类AbstractExtentChartProvider。
eg:
实现抽象方法:createChart (返回第三步的实例对象xxxChart,后台图表对象)。
Code Block |
---|
|
package com.fr.plugin.extended.chart.demo;
import com.fr.extended.chart.AbstractChart;
import com.fr.extended.chart.AbstractExtentChartProvider;
/**
* Created by shine on 2018/3/24.
*/
public class Demo extends AbstractExtentChartProvider {
@Overrideif (xComboBox == null) {
xComboBox = new UIComboBox();
yComboBox = new UIComboBox();
protected AbstractChart createChart() {
zComboBox return= new DemoChartUIComboBox();
}
}
|
图表界面插件接口xxxUI,继承AbstractExtendedChartUIProvider。
eg:实现接口方法:getTableDataSourcePane && getReportDataSourcePane (返回第四步定义的两个数据配置界面的实例对象)&&getIconPath(表单工具栏拖拽图表小图标)。
Code Block |
---|
|
package com.fr.plugin.extended.chart.demo;
import com.fr.design.mainframe.chart.gui.data.report.AbstractReportDataContentPane;
import com.fr.extended.chart.AbstractExtendedChartTableDataPane;
import com.fr.extended.chart.AbstractExtendedChartUIProvider;
/**
* Created by shine on 2018/3/24.
*/
public class DemoUI extends AbstractExtendedChartUIProvider {
@Override
protected AbstractExtendedChartTableDataPane getTableDataSourcePane() {
expect = new UIComboBox();
actual = new UIComboBox();
}
return new UIComboBox[]{
xComboBox,
yComboBox,
return new DemoTableDataPane();
zComboBox,
}
@Override
protected AbstractReportDataContentPane getReportDataSourcePane() {expect,
return new DemoReportDataPane();
}actual
@Override
public};
String getIconPath() {}
@Override
return "com/fr/plugin/extended/chart/demo/icon.png";
}
}
|
第六步:插件相关。
新建plugin.xml文件,内容拷贝下面内容,需要更改的字段有:
id:插件id。com.fr.plugin.demoChart 换成自己的,比如com.fr.plugin.xxxChart。
name:插件名称。DEMO图表 换成自己的。
function-recorder: 插件功能点记录。很重要!!!。class写第三步定义的类的路径即可。同时需要给第三步定义的类添加注解@FunctionRecorder,方法addJSON添加注解@ExecuteFunctionRecord
IndependentChartProvider:图表接口。class写第五步中的xxx路径。plotID为 第三步中图表对象实现的抽象方法getChartID返回的结果。
IndependentChartUIProvider:图表UI接口。class写第五步中的xxxUI路径。plotID为 第三步中图表对象实现的抽象方法getChartID返回的结果。
Code Block |
---|
title | plugin.xml |
---|
collapse | true |
---|
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?><plugin>
<id>com.fr.plugin.demoChart</id>
<name><![CDATA[DEMO图表]]></name>
<active>yes</active>
<version>1.0.0</version>
<env-version>10.0</env-version>
<jartime>2018-3-31</jartime>
<vendor>finereport.shine</vendor>
<description><![CDATA[给开发者参考的图表插件demo]]></description>
<change-notes><![CDATA[]]></change-notes>
<function-recorder class="com.fr.plugin.demo.DemoChart"/>
<extra-chart>protected void populate(DemoDataConfig dataConf) {
populateField(xComboBox, dataConf.getX());
targetName.setText(dataConf.getTargetName());
populateField(yComboBox, dataConf.getY());
populateField(zComboBox, dataConf.getZ());
populateFunctionField(expect, expectFunction, dataConf.getExpect());
populateFunctionField(actual, actualFunction, dataConf.getActual());
}
@Override
protected DemoDataConfig update() {
<IndependentChartProvider class="com.fr.plugin.demo.Demo" plotID="DEMO_CHART"/>
</extra-chart>DemoDataConfig dataConfig = new DemoDataConfig();
<extra-chart-designer>
updateField(xComboBox, dataConfig.getX());
<IndependentChartUIProvider class="com.fr.plugin.demo.DemoUI" plotID="DEMO_CHART"/>
</extra-chart-designer>
</plugin> |
Code Block |
---|
title | function-recorder |
---|
collapse | true |
---|
|
/**
* Created by shine on 2018/3/24.
*/
@FunctionRecorder
public class DemoChart extends AbstractChart<DemoDataConfig>{
@ExecuteFunctionRecord
@Override
protected void addJSON(DemoDataConfig dataConfig, JSONObject jsonObject, Repository repo) throws JSONException {
dataConfig.setTargetName(targetName.getText());
updateField(yComboBox, dataConfig.getY());
updateField(zComboBox, dataConfig.getZ());
updateFunctionField(expect, expectFunction, dataConfig.getExpect());
JSONArray array = JSONFactory.createJSON(JSON.ARRAYupdateFunctionField(actual, actualFunction, dataConfig.getActual());
return dataConfig;
List<Object> xValues = dataConfig.getX().getValues(); }
} |
最后,在chart的addjson里面,获取相应字段的values即可。
数据界面-数据集 字段名(也可自定义字符串)组成一个字段(系列名使用字段名)。
首先,DemoTableDataPane中复写createExtendedCustomFieldComboBoxPane方法,返回new ExtendedCustomFieldComboBoxPane()。
Code Block |
---|
|
@Override
protected ExtendedCustomFieldComboBoxPane createExtendedCustomFieldComboBoxPane() {
return new List<Object> yValuesExtendedCustomFieldComboBoxPane();
} |
最后,在DemoChart中,直接获取相应的values即可。
Code Block |
---|
|
List<Object> customNames = dataConfig.getYgetCustomNameField().getValues();
List<Object> zValuescustomValues = dataConfig.getZgetCustomValueField().getValues(); |
字段的配置下拉框含有 无 这个选项。
使用组件 UIComboBoxWithNone即可。
Code Block |
---|
|
private UIComboBoxWithNone seriesName;
......其余省略,主要看@FunctionRecorder && @ExecuteFunctionRecord |
简单的开发到此结束,如果想要联动or超链or导出or公式等,请参考开发进阶空数据提示(调用内置图表 空数据提示接口)。
在前期准备第二步写的前端图表对象xxxWrapper中添加方法_emptyData。根据参数options返回是否是空数据。
Code Block |
---|
_emptyData: function (options) {
return options.series.data.length === 0;
} |