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

Page tree

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

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 65 Next »

前言

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

解决方法

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

 

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

关键接口

插件图表接口

 

IndependentChartProvider
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类即可,并实现里面具体的方法,示例如下:

DemoChartsPie extends AbstractIndependentChartsProvider
package com.fr.plugins.democharts.commenDataPanePie;

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


/**
 * Created 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(),
    };

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

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

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

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

    /**
     * 定义在设计器里展现的图的路径
     *
     * @return 图的路径
     */
    @Override
    public String getChartImagePath() {
        return "com/fr/plugins/democharts/customDataPanePie/images/pie256.png";
    }

    /**
     * @return 插件的API等级
     */
    @Override
    public int currentAPILevel() {
        return CURRENT_API_LEVEL;
    }

}



 

插件图表界面接口

 

IndependentChartUIProvider
package com.fr.design.chart.fun;

/**
 * Created by eason on 14/12/29.
 *
 * @since 8.0
 * 自定义图表类型设设计界面接口
 */
public interface IndependentChartUIProvider extends Level {

 String XML_TAG = "IndependentChartUIProvider";

 int CURRENT_API_LEVEL = 3;


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

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

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

DemoChartsPieUI extends AbstractIndependentChartsUI
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 DemoChartsPieUI extends AbstractIndependentChartsUI {

    /**
     * @param plotID
     * @return 图表样式面板,用户需要实现
     */
    @Override
    public ChartsConfigPane getChartConfigPane(String plotID) {
        return new ChartConfigPane();
    }

    /**
     * @return 插件的API等级
     */
    @Override
    public int currentAPILevel() {
        return CURRENT_API_LEVEL;
    }

}
 

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

关键抽象类

图表配置面板类

ChartsConfigPane
  
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 populate(ChartCollection collection) {
        if (StableUtils.classInstanceOf(collection.getSelectedChart().getClass(),accptType())) {
            populate(collection, (T)collection.getSelectedChart());
        }
    }

    protected abstract void populate(ChartCollection collection, T selectedChart);

    @Override
    public void update(ChartCollection collection) {
        if (StableUtils.classInstanceOf(collection.getSelectedChart().getClass(),accptType())) {
            update(collection, (T)collection.getSelectedChart());
        }
    }

    protected abstract void update(ChartCollection collection, T selectedChart);

    @Override
    protected JPanel createContentPane() {
        return new JPanel();
    }

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

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


 

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

import com.fr.chart.chartattr.ChartCollection;
import com.fr.design.mainframe.chart.ChartsConfigPane;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * Created by mengao on 2017/4/26.
 * 图表样式面板,需要继承ChartsConfigPane
 * 需要实现方法:populate
 * 需要实现方法:update
 */
public class ChartConfigPane extends 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());
}
}


图表类

Charts
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类需要继承此抽象类,并实现相应方法,示例如下:

 

PieChart extends Charts
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.put(wrapper);
        }
        return series;
    }

    private JSONArray pointJSONArray(int index) throws JSONException {
        NormalChartData normalChartData = getChartData();
        int categoriesLen = normalChartData.getCategoryLabelCount();
        JSONArray point = JSONArray.create();
        for (int i = 0; i < categoriesLen; i++) {
            JSONObject item = JSONObject.create();
            //将分类名给name
            String name = normalChartData.getCategory_array()[i].toString();
            item.put("name", name);
            if (normalChartData.getSeries_value_2D().length > 0) {
                //将点的值给data
                item.put("value", normalChartData.getSeries_value_2D()[index][i]);
            }
            point.put(item);
        }
        return point;
    }

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


}

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

 

XML关键配置

 

plugin.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>

简单效果图

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

 

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

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

示例源码

如果您希望看示例源码,您可以看这里:http://cloud.finedevelop.com:2015/users/mango/repos/plugins-democharts/browse

  • No labels