【仅供内部供应商使用,不提供对外解答和培训】

Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

10.0工程请移步基于finekit

前言

FineReport除了内置的图表、新特性图表插件外,还提供了第三方图表开发的API,方便进行个性化、第三方的图表开发。但是第三方图表API接口过于复杂,用户很难快速的实现并使用自己想使用的第三方新图表。

...

在原有的图表接口基础之上,对接口进行了简化和修改,让用户可以快速的写出第三方图表插件并使用。


下面介绍下重要的接口,和简单的实现(使用公共的数据配置面板,自定义数据面板参考页面底部链接demo):

关键接口

插件图表接口


 

Code Block
titleIndependentChartProvider
collapsetrue
package com.fr.chart.fun;

import com.fr.chart.chartattr.Chart;
import com.fr.stable.fun.Level;

/**
 * Created by eason on 15/4/21.
 * 图表接口
 */
public interface IndependentChartProvider extends Level {

 String XML_TAG = "IndependentChartProvider";

 int CURRENT_API_LEVEL = 3;

 /**
 * 图表的国际化的名字的key
 *
 * @return 图表国际化的名字的key
 */
 String getChartName();

 /**
 * 该种图表所有的图表类型,比如柱形图就有堆积柱形图,百分比堆积柱形图等等
 *
 * @return 所有的图表类型
 */
 Chart[] getChartTypes();

 /**
 * 图表在web端展现时需要的JS文件
 *
 * @return JS文件数组
 */
 String[] getRequiredJS();

 /**
 * JS对象名,该对象一般是一个函数,执行后会在给定的dom中绘制图表
 *
 * @return JS对象名
 */
 String getWrapperName();

 /**
 * 定义在设计器里展现的图的路径
 *
 * @return 图的路径
 */
 String getChartImagePath();
/**
}
上述接口用户需要直接实现,里面具体需要实现的方法示例如下:
 * 当前接口的API等级,用于判断是否需要升级插件
 *
 * @return API等级
 */
int currentAPILevel();

}

上述接口您不必实现,只需要继承实现了该接口的抽象类:AbstractIndependentChartsProvider类即可,并实现里面具体的方法,示例如下:

Code Block
titleDemoChartsPie implements IndependentChartProviderextends AbstractIndependentChartsProvider
collapsetrue
package com.fr.plugins.democharts.piecommenDataPanePie;

import com.fr.chart.chartattr.Chart;
import com.fr.chart.fun.impl.IndependentChartProviderAbstractIndependentChartsProvider;


/**
public class* DemoChartsPie implements IndependentChartProviderCreated by mengo on 16/5/11.
 * 自定义图表,需要继承AbstractIndependentChartsProvider
 * 需要实现方法:getChartName
 * 需要实现方法:getWrapperName
 * 需要实现方法:getChartTypes
 * 需要实现方法:getChartImagePath
 * 需要实现方法:getRequiredJS
 * 需要实现方法:currentAPILevel
 */
public class DemoChartsPie extends AbstractIndependentChartsProvider {

    public static pieChart[] charts = new pieChart[] {
            new pieChart(),
    };


    @Override/**
    public * String图表的国际化的名字的key
 getChartName() {
   *
     return "用户自定义图表";
* @return 图表国际化的名字的key
     }
*/
    @Override
    public String[] getRequiredJSgetChartName() {
        return new String[]{ "用公共的数据配置面板图表";
    }

    /**
     * 图表在web端展现时需要的JS文件
     *
     "/com/fr/plugins/democharts/common/web/echarts.bridge.js"
  * @return JS文件数组
      };
    }*/
    @Override
    public String[] getWrapperNamegetRequiredJS() {
        return "EChartsFactory";
    }

 new String[]{
   @Override
    public Chart[] getChartTypes() {
      "/com/fr/plugins/democharts/common/web/echarts.bridge.js"
       return charts};
    }

    @Override/**
    public String getChartImagePath() {* JS对象名,该对象一般是一个函数,执行后会在给定的dom中绘制图表
     *
   return "com/fr/plugins/democharts/pie/images/pie256.png";
    }

 * @return JS对象名
     */
    @Override
    public intString currentAPILevelgetWrapperName() {
        return 3"EChartsFactory";
    }
}

 

插件图表界面接口

 

Code Block
titleIndependentChartUIProvider
collapsetrue
package com.fr.design.chart.fun;


    /**
     * 该种图表所有的图表类型,比如柱形图就有堆积柱形图,百分比堆积柱形图等等
 
Created
 
by
 
eason
 
on 14/12/29. *
 *
     * 
@since
@return 
8.0
所有的图表类型
 
*
   
自定义图表类型设设计界面接口
 */
public interface IndependentChartUIProvider extends Level

    @Override
    public Chart[] getChartTypes() {
  
String
 
XML_TAG
 
=
 
"IndependentChartUIProvider";
 
int
 
CURRENT_API_LEVEL
 
=
return 
3
charts;
    }

    /**
     * 
当前接口的API等级,用于判断是否需要升级插件
定义在设计器里展现的图的路径
     *
     * @return 
API等级
图的路径
     */
int
 
currentAPILevel(); /**
 
*
 
图表配置面板
 
*
@Override
 
*
 
@return图表配置面板
 
*/
 
ChartEditPaneProvider
public 
getChartConfigPane(
String 
plotID
getChartImagePath()
;
 {
......(其他方法不用实现) }

此接口用户不必实现 ,只需要继承实现了该接口的抽象类: AbstractIndependentChartUI4Custom 类即可,并实现相应方法,示例如下:

Code Block
titleDemoChartsPieUI extends AbstractIndependentChartUI4Custom
collapsetrue
package com.fr.plugins.democharts.pie; import com.fr.design.chart.fun.impl.AbstractIndependentChartUI4Custom; import com.fr.design.gui.chart.ChartEditPaneProvider; public class DemoChartsPieUI extends AbstractIndependentChartUI4Custom {
        return "com/fr/plugins/democharts/customDataPanePie/images/pie256.png";
    }

    /**
     * @return 插件的API等级
     */
    @Override
    public 
ChartEditPaneProvider
int 
getChartConfigPane
currentAPILevel(
String plotID
) {
        return 
new ChartConfigPane()
CURRENT_API_LEVEL;
    }

@Override public int currentAPILevel() { return 3; } }

关键抽象类

图表配置面板类
}




插件图表界面接口


Code Block
titleThirdChartEditPaneIndependentChartUIProvider
collapsetrue
package com.fr.design.mainframe.chart;

import javax.swing.*;
import java.awt.*.fun;

/**
 * Created by mengaoeason on 201714/512/329.
 */
public abstract class ThirdChartEditPane extends ChartEditPane implements ChartEditPaneProvider, ThirdChartInterface * @since 8.0
 * 自定义图表类型设设计界面接口
 */
public interface IndependentChartUIProvider extends Level {

protected abstractString void populateBean(Object ob)XML_TAG = "IndependentChartUIProvider";

protected abstract void updateBean(Object ob);
    ......

}

 

用户的图表配置面板ChartConfigPane类需要继承此抽象类,并实现相应的方法,示例如下: Code Block
titleChartConfigPane extends ThirdChartEditPane
collapsetrue
 package com.fr.plugins.democharts.pie; import com.fr.design.mainframe.chart.ThirdChartEditPane; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;
int CURRENT_API_LEVEL = 3;


/**
 * 当前接口的API等级,用于判断是否需要升级插件
 *
 * @return API等级
 */
int currentAPILevel();
 /**
 * 图表配置面板
 *
 * @return图表配置面板
 */
 ThirdChartConfigPane getChartConfigPane(String plotID);

 ......(其他方法不用实现)
}

此接口您不必实现 ,只需要继承实现了该接口的抽象类:AbstractIndependentChartsUI类即可,并实现相应方法,示例如下:

Code Block
titleDemoChartsPieUI extends AbstractIndependentChartsUI
collapsetrue
package com.fr.plugins.democharts.commenDataPanePie;

import com.fr.design.chart.fun.impl.AbstractIndependentChartsUI;
import com.fr.design.mainframe.chart.ChartsConfigPane;


/**
 * Created by mengao on 2017/4/26.
 *
/
 自定义图表类型设设计界面,需要继承AbstractIndependentChartsUI
 * 需要实现方法:getChartConfigPane
 * 需要实现方法:currentAPILevel
 */
public class 
ChartConfigPane
DemoChartsPieUI extends 
ThirdChartEditPane
AbstractIndependentChartsUI {

    /**
 
private
 
pieChart
 
pieChart;
  * @param 
JPanel
plotID
 
northJpane
 
=
 
new
 
JPanel();
 * @return 图表样式面板,用户需要实现
 
JPanel
 
centerJpane
 
=
 
new JPanel();
 */
    
JLabel
@Override
 
nameJLable
 
=
 
new
 
JLabel("请输入内容:");
public ChartsConfigPane getChartConfigPane(String plotID) {
      
JTextField
 
value
 
=
return new 
JTextField
ChartConfigPane();
    
JButton
}

 
updateButton
 
=
 
new JButton("确定");
 /**
     
public
* 
ChartConfigPane() //构造方法
@return 插件的API等级
     
{
*/
    @Override
    public 
this.setLayout(new BorderLayout
int currentAPILevel()
);
 {
        
northJpane.setLayout(new GridLayout(3, 2))
return CURRENT_API_LEVEL;
    
northJpane.add(nameJLable); northJpane.add(value); this.add(northJpane, BorderLayout.NORTH); centerJpane.add(updateButton, BorderLayout.CENTER); this.add(centerJpane, BorderLayout.CENTER); this.setSize(200, 200); this.setVisible(true); updateButton.addActionListener(new ColorEventListener()); } // 内部类ColorEventListener,实现ActionListener接口 class ColorEventListener implements ActionListener { @Override
}

}
 

注意:如果您想使用自己的数据配置面板,需要覆写getTableDataSourcePane(Plot plot, ChartDataPane parent)和getReportDataSourcePane(Plot plot, ChartDataPane parent)方法,并自定义数据编辑面板、chartData、Definition等类,具体参考底部链接中的plugins-demoChart插件。

关键抽象类

图表配置面板类

Code Block
titleChartsConfigPane
collapsetrue
  
package com.fr.design.mainframe.chart;

import com.fr.chart.chartattr.ChartCollection;
import com.fr.chart.chartattr.Charts;
import com.fr.general.Inter;
import com.fr.stable.StableUtils;

import javax.swing.*;

/**
 * Created by mengao on 2017/5/16.
 */
public abstract class ChartsConfigPane <T extends Charts> extends AbstractChartAttrPane {

    public final static String CHART_STYLE_TITLE = Inter.getLocText("Chart-Style_Name");

    public abstract Class<? extends Charts> accptType();

    @Override
    public void 
actionPerformed
populate(
ActionEvent
ChartCollection 
e
collection) {
        
updateBean(pieChart);
if (StableUtils.classInstanceOf(collection.getSelectedChart().getClass(),accptType())) {
        
}
    
}
populate(collection, (T)collection.getSelectedChart());
    
@Override
    
public
}
 
void
 
populateBean(Object
 
ob)
 
{
}

    protected abstract void populate(ChartCollection 
if
collection, 
(ob instanceof pieChart) {
T selectedChart);

    @Override
    public void update(ChartCollection 
pieChart = (pieChart) ob;
collection) {
        if (StableUtils.classInstanceOf(collection.getSelectedChart().getClass(),accptType())) {
            
value.setText(pieChart.getCustomData
update(collection, (T)collection.getSelectedChart());
        }
    }

    
@Override
protected abstract void update(ChartCollection 
public
collection, 
void updateBean(Object ob) {
T selectedChart);

    @Override
    
if
protected JPanel createContentPane(
ob instanceof pieChart
) {
        return 
pieChart pieChart = (pieChart) ob;
new JPanel();
    }

    @Override
    public 
pieChart.setCustomData(value.getText());
String getIconPath() {
        
}
return "com/fr/design/images/chart/ChartStyle.png";
    }

    @Override
    public String title4PopupWindow() {
        return CHART_STYLE_TITLE;
    }
}



图表类您的图表配置面板需要继承此抽象类,并实现相应的方法,示例如下:
Code Block
title
ThirdChartEditPane
ChartConfigPane extends ChartsConfigPane
collapsetrue
package com.fr.
chart
plugins.democharts.
chartattr
commenDataPanePie;

import com.fr.
base
chart.
chart
chartattr.
BaseChartGlyph
ChartCollection;
import com.fr.
base
design.mainframe.chart.
BaseChartPainter
ChartsConfigPane;

import 
com
javax.
fr.base.chart.ChangeConfigProvider
swing.*;
import 
com
java.
fr.base.chart.chartdata.ChartData
awt.*;
import 
com
java.
fr
awt.
chart
event.
chartglyph.ChartGlyph
ActionEvent;
import 
com
java.
fr
awt.
chart
event.
chartglyph.PlotGlyph
ActionListener;
import com.fr.stable.web.Repository;

import java.awt.*; import java.awt.geom.RectangularShape; import java.util.Iterator; import java.util.Map;
/**
 * Created by mengao on 2017/
5
4/
3
26.
 * 
用户使用第三方图表需要继承chart父类
图表样式面板,需要继承ChartsConfigPane
 *
/
 需要实现方法:populate
public
 
abstract
* 需要实现方法:update
 */
public class 
ThirdChart
ChartConfigPane extends 
Chart implements BaseChartGlyph { public String getChartID() public void writeXML(XMLPrintWriter xmlPrintWriter) public void readXML(XMLableReader xmLableReader)  public JSONObject toJSONObject(Repository repository) throws JSONException  public Image toImage(int i, int i1, int i2) public Image toImage(int i, int i1, int i2, CallbackEvent callbackEvent, ChartDataParam chartDataParam) ...... }

 

用户的图表配置面板ChartConfig类需要继承此抽象类,并实现

Code Block
titlepieChart extends ThirdChart
collapsetrue
package com.fr.plugins.democharts.pie; import com.fr.base.chart.chartdata.CallbackEvent; import com.fr.base.chart.chartdata.ChartDataParam; import com.fr.chart.chartattr.ThirdChart; import com.fr.json.JSONException; import com.fr.json.JSONObject; import com.fr.stable.web.Repository; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLableReader; import java.awt.*; public class pieChart extends ThirdChart { private String customData= "demo"; public String getCustomData() { return customData; } public void setCustomData(String customData) { this.customData = customData; } @Override public void writeXML(XMLPrintWriter xmlPrintWriter) { super.writeXML(xmlPrintWriter); xmlPrintWriter.startTAG("customChartDemo")
ChartsConfigPane<PieChart> {
  private JPanel northJpane = new JPanel();
private JPanel centerJpane = new JPanel();
private JLabel nameJLable = new JLabel("请输入内容:");
private JButton updateButton = new JButton("确定");

protected JTextField value = new JTextField();
protected ChartCollection chartCollection;



public ChartConfigPane() //构造方法
{
    this.setLayout(new BorderLayout());
    northJpane.setLayout(new GridLayout(3, 2));
    northJpane.add(nameJLable);
    northJpane.add(value);
    this.add(northJpane, BorderLayout.NORTH);
    centerJpane.add(updateButton, BorderLayout.CENTER);
    this.add(centerJpane, BorderLayout.CENTER);
    this.setSize(200, 200);
    this.setVisible(true);
    updateButton.addActionListener(new ColorEventListener());
}

// 内部类EventListener,实现ActionListener接口
class ColorEventListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        update(chartCollection, (T)chartCollection.getSelectedChart());
    }
}
@Override
public Class<? extends Charts> accptType() {
    return PieChart.class;
}

@Override
protected void populate(ChartCollection collection, PieChart selectedChart) {
    this.chartCollection=collection;
    value.setText(selectedChart.getCustomData());
}

@Override
protected void update(ChartCollection collection, PieChart selectedChart) {
    selectedChart.setCustomData(value.getText());
}
}


图表类

Code Block
titleCharts
collapsetrue
package com.fr.chart.chartattr;

import com.fr.base.chart.BaseChartGlyph;
import com.fr.base.chart.chartdata.ChartData;
import com.fr.chart.chartglyph.ChartGlyph;
import com.fr.json.JSONException;
import com.fr.json.JSONObject;
import com.fr.stable.web.Repository;

/**
 * Created by mengao on 2017/5/3.
 * 用户使用第三方图表需要继承chart父类
 */
public abstract class Charts <T extends ChartData> extends Chart  {
    protected T ChartData;

    public T getChartData() {
        return ChartData;
    }

    public void setChartData(T chartData) {
        ChartData = chartData;
    }

    protected abstract String getChartID();

    public Charts() {
        ChartsPlot chartsPlot = new ChartsPlot();
        chartsPlot.setPlotID(getChartID());
        this.setPlot(chartsPlot);
    }

    @Override
    public BaseChartGlyph createGlyph(ChartData chartData) {
        ChartGlyph chartGlyph = new ChartGlyph(){
            public JSONObject toJSONObject(Repository repo, double width, double height) throws JSONException {
                return toJSON(repo);
            }
        };

        setChartData((T)chartData);
        chartGlyph.setWrapperName(this.getWrapperName());
        chartGlyph.setRequiredJS(this.getRequiredJS());
        chartGlyph.setChartImagePath(this.getImagePath());

        return chartGlyph;
    }
    public abstract JSONObject toJSON (Repository repo) throws JSONException;
}


您的图表配置面板ChartConfig类需要继承此抽象类,并实现相应方法,示例如下:


Code Block
titlePieChart extends Charts
collapsetrue
package com.fr.plugins.democharts.commonpie;

import com.fr.chart.chartattr.Charts;
import com.fr.chart.chartdata.NormalChartData;
import com.fr.json.JSONArray;
import com.fr.json.JSONException;
import com.fr.json.JSONObject;
import com.fr.stable.web.Repository;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLableReader;

import java.text.DecimalFormat;
import java.text.NumberFormat;


/**
 * Created by mengao on 2017/4/26.
 * chart类,需要继承Charts
 * 需要实现方法:getChartID
 * 需要实现方法:writeXML
 * 需要实现方法:readXML
 * 需要实现方法:toJSON
 */
public class PieChart extends Charts<NormalChartData> {
    private String customData = "公共数据配置面板demo";

    private static final NumberFormat format = new DecimalFormat("##%");


    public String getCustomData() {
        return customData;
    }

    public void setCustomData(String customData) {
        this.customData = customData;
    }

    @Override
    public void writeXML(XMLPrintWriter xmlPrintWriter) {
        super.writeXML(xmlPrintWriter);
        xmlPrintWriter.startTAG("customChartDemo")
                .attr("custom", getCustomData())
                .end();
    }

    @Override
    public void readXML(XMLableReader xmLableReader) {
        super.readXML(xmLableReader);
        if (xmLableReader.isChildNode()) {
            String tagName = xmLableReader.getTagName();
            if (tagName.equals("customChartDemo")) {
                setCustomData(xmLableReader.getAttrAsString("custom", "111"));
            }
        }
    }

    /**
     * 读出字符串,然后传到前台
     * 注意:需要获取数据配置中的数据,使用getChartData()方法
     */
    @Override
    //tojson的时候注意用getChartData()方法获取当前数据集,然后自主拼接成json
    public JSONObject toJSON(Repository repo) throws JSONException {

        JSONObject jsonObject = JSONObject.create();
        jsonObject.put("series", seriesJSONArray())
                .put("title", JSONObject.create().put("text", getCustomData()));
        return jsonObject;
    }

    private JSONArray seriesJSONArray() throws JSONException {
        NormalChartData normalChartData = getChartData();
        int seriesLen = normalChartData.getSeriesCount();
        String radius = format.format(1.0 / seriesLen);
        //对系列循环
        JSONArray series = JSONArray.create();
        for (int index = 0; index < seriesLen; index++) {
            JSONObject wrapper = JSONObject.create()
                    .put("type", "pie")
                    .put("data", pointJSONArray(index)) //将每个系列值给data
                    .put("name", normalChartData.getSeries_array()[index].toString());//将系列名给系列
            if (seriesLen > 1) {
                JSONArray center = JSONArray.create()
                        .put(format.format((float) index / (seriesLen + 1) + 0.20))
                        .put("55%");
                wrapper.put("radius", radius)
                        .put("center", center);
            }
            series.attr("custom", getCustomData())
put(wrapper);
        }
        return .end()series;
    }

    @Override
private JSONArray   public void readXML(XMLableReader xmLableReader)pointJSONArray(int index) throws JSONException {
        super.readXML(xmLableReaderNormalChartData normalChartData = getChartData();
        int if (xmLableReader.isChildNode()) {categoriesLen = normalChartData.getCategoryLabelCount();
        JSONArray point   String tagName = xmLableReaderJSONArray.getTagNamecreate();

        for (int i = 0; i <  if(tagName.equals("customChartDemo"))categoriesLen; i++) {
            JSONObject item =  setCustomData(xmLableReader.getAttrAsString("custom","111")JSONObject.create();
            }//将分类名给name
        }
    }

String name   @Override
    public JSONObject toJSONObject(Repository repository) throws JSONException {= normalChartData.getCategory_array()[i].toString();
        JSONObject jsonObject = new JSONObject(item.put("name", name);
            if jsonObject.put("customChartDemo",getCustomData());
(normalChartData.getSeries_value_2D().length > 0) {
           return jsonObject;
    }

//将点的值给data
       @Override
    public Image toImage(int i, int i1, int i2) {
  item.put("value", normalChartData.getSeries_value_2D()[index][i]);
       return null;
    }

    @Override
    public Image toImage(int i, int i1, int i2, CallbackEvent callbackEvent, ChartDataParam chartDataParam) { point.put(item);
        }
        return nullpoint;
    }

    @Override
    public String getChartID() {
        return "DemoChartsPiePlotChartsPieWithCommenDataPane";
    }


}

关键配置

code


注意:在toJSON中您如果需要获取数据配置中的数据,请使用getChartData()方法获取chartData对象,并将其转化为您需要的格式,具体参考demo


XML关键配置


Code Block
titleplugin.xml
<extra-core>
    <JavaScriptFileHandler class="com.fr.plugins.democharts.common.web.EChartsFileLoader"/>
</extra-core>
<extra-chart>
 <IndependentChartProvider class="com.fr.plugins.democharts.pie.DemoChartsPie"
 plotID="DemoChartsPiePlot"/>
</extra-chart>
<extra-chart-designer>
 <IndependentChartUIProvider class="com.fr.plugins.democharts.pie.DemoChartsPieUI"
 plotID="DemoChartsPiePlot"/>
</extra-chart-designer>

 

 

 

 

 

 

简单效果图

您可以自定义图表数据配置面板,更加灵活。(左:默认数据配置面板,右:自定义的数据配置面板)


Image AddedImage Added

您需要自定义图表属性配置面板,让它为您设置图表的各种属性:

Image Added

通过配置面板配置好数据和属性后,您可以预览您图表配置好之后的效果,demo展示效果如下:(左:默认数据配置面板demo,右:自定义数据配置面板demo)

Image AddedImage Added

demo工程:

View file
nameplugins-democharts.zip
height250