Repository: knowm/XChart
Pull request #372 (2019-12-03 00:59:49)

#176:add box plot
Hey @timmolter 

 I add box plot(#176 )
This is the effect picture, the example is `xchart-demo/src/main/java/org/knowm/xchart/demo/charts/boxPlot/BoxPlot01.java `

![Screenshot_2019-12-03_08-58-16](https://user-images.githubusercontent.com/57353473/70007402-286c5280-15ab-11ea-9c9b-2239fe285351.png)

This is the main logic of my box plot

Each box plot is calculated from all y values corresponding to the same x value. The calculation formula is shown below:
Example, all y values are 1, 2, 3
First arrange all corresponding y values from small to large
First quartile position = q1 = (n +1) / 4
Second quartile position = q2 = (n + 1) / 2
Third quartile position = q3 = 3 * (n + 1) / 4
If the calculation result is an integer, the corresponding position is taken
Q1 = 1, Q2 = 2, Q3 = 3
Then the first quartile = Q1 = 1, the second quartile = Q2 = 2, and the third quartile = Q3 = 3
Otherwise calculated with the following formula
For example, 1, 2, 3, 4
q1 = (4 +1) /4=1.25
q2 = (4 + 1) /2=2.5
q3 = 3 * (4 + 1) /4=3.75
then
Q1 = 1+ （2-1） * 0.25 = 1.25
Q2 = 2 + （3-2） * 0.5 = 2.5
Q3 = 3 + （4-3） * 0.75 = 3.75
Upper limit = Q3 + 1.5 * IQR = Q3 + 1.5 * (Q3-Q1)
Lower limit = Q1-1.5 * IQR = Q1-1.5 * (Q3-Q1)

Please review the code for me. If you are not satisfied, please tell me in time. I will give you a satisfactory answer.

Hava a nice day!


Patch:
diff --git a/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/boxPlot/BoxPlotChart01.java b/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/boxPlot/BoxPlotChart01.java
new file mode 100644
index 00000000..e685b232
--- /dev/null
+++ b/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/boxPlot/BoxPlotChart01.java
@@ -0,0 +1,41 @@
+package org.knowm.xchart.demo.charts.boxPlot;
+
+import java.util.Arrays;
+
+import org.knowm.xchart.BoxPlotChartBuilder;
+import org.knowm.xchart.BoxPlotChart;
+import org.knowm.xchart.BoxPlotSeries;
+import org.knowm.xchart.SwingWrapper;
+import org.knowm.xchart.demo.charts.ExampleChart;
+import org.knowm.xchart.style.Styler.ChartTheme;
+
+/*
+ * Box Plot with 3 series
+ */
+public class BoxPlotChart01 implements ExampleChart<BoxPlotChart> {
+
+  public static void main(String[] args) {
+    ExampleChart<BoxPlotChart> exampleChart = new BoxPlotChart01();
+    BoxPlotChart chart = exampleChart.getChart();
+    new SwingWrapper<BoxPlotChart>(chart).displayChart();
+  }
+
+  @Override
+  public BoxPlotChart getChart() {
+
+    // Create Chart
+    BoxPlotChart chart =
+        new BoxPlotChartBuilder()
+        .title("box plot demo")
+        .xAxisTitle("Color")
+        .yAxisTitle("temperature")
+        .theme(ChartTheme.GGPlot2)  
+        .build();
+    // Series
+    BoxPlotSeries[] boxSeries = new BoxPlotSeries[3];
+    boxSeries[0] = chart.addSeries("aaa", Arrays.asList(40, 30, 20, 60, 50));
+    boxSeries[1] = chart.addSeries("bbb", Arrays.asList(-20, -10, -30, -15, -25));
+    boxSeries[2] = chart.addSeries("ccc", Arrays.asList(50, -20));
+    return chart;
+  }
+}
diff --git a/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/boxPlot/BoxPlotChart02.java b/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/boxPlot/BoxPlotChart02.java
new file mode 100644
index 00000000..3d5a2bee
--- /dev/null
+++ b/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/boxPlot/BoxPlotChart02.java
@@ -0,0 +1,47 @@
+package org.knowm.xchart.demo.charts.boxPlot;
+
+import java.util.Arrays;
+
+import org.knowm.xchart.BoxPlotChartBuilder;
+import org.knowm.xchart.BoxPlotChart;
+import org.knowm.xchart.BoxPlotSeries;
+import org.knowm.xchart.SwingWrapper;
+import org.knowm.xchart.demo.charts.ExampleChart;
+import org.knowm.xchart.style.Styler.ChartTheme;
+
+/*
+ * Box Plot with 3 series
+ * and draw errorBars
+ */
+public class BoxPlotChart02 implements ExampleChart<BoxPlotChart> {
+
+  public static void main(String[] args) {
+    ExampleChart<BoxPlotChart> exampleChart = new BoxPlotChart02();
+    BoxPlotChart chart = exampleChart.getChart();
+    new SwingWrapper<BoxPlotChart>(chart).displayChart();
+  }
+
+  @Override
+  public BoxPlotChart getChart() {
+
+    // Create Chart
+    BoxPlotChart chart =
+        new BoxPlotChartBuilder()
+        .title("box plot show all point")
+        .xAxisTitle("Color")
+        .yAxisTitle("temperature")
+        .theme(ChartTheme.Matlab)
+        .build();
+    // Series
+    BoxPlotSeries[] boxSeries = new BoxPlotSeries[3];
+    boxSeries[0] = chart.addSeries("aaa",
+        Arrays.asList(9634.37, 23886.43, 13828.96, 7773.08, 14959.32, 8046.95, 6547.51, 9528.85, 9241.53, 9353.79, 8224.60, 10436.48, 10399.62, 15067.39, 8505.73, 9398.87, 11611.29, 12280.94, 9631.96));
+    boxSeries[1] = chart.addSeries("bbb",
+        Arrays.asList(7000, 8000, 9000));
+    boxSeries[2] = chart.addSeries("ccc",
+        Arrays.asList(7000, 8000, null, 9000));
+    chart.getStyler().setShowWithinAreaPoint(true);
+    chart.getStyler().setToolTipsEnabled(true);
+    return chart;
+  }
+}
diff --git a/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/boxPlot/BoxPlotChart03.java b/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/boxPlot/BoxPlotChart03.java
new file mode 100644
index 00000000..e1ba81c5
--- /dev/null
+++ b/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/boxPlot/BoxPlotChart03.java
@@ -0,0 +1,53 @@
+package org.knowm.xchart.demo.charts.boxPlot;
+
+import java.util.Arrays;
+
+import org.knowm.xchart.BoxPlotChartBuilder;
+import org.knowm.xchart.BoxPlotChart;
+import org.knowm.xchart.BoxPlotSeries;
+import org.knowm.xchart.SwingWrapper;
+import org.knowm.xchart.demo.charts.ExampleChart;
+import org.knowm.xchart.style.Styler.ChartTheme;
+
+/*
+ * Box Plot with 6 series
+ * and show ToolTips
+ * and Y-Axis is logarithmic
+ */
+public class BoxPlotChart03 implements ExampleChart<BoxPlotChart> {
+
+  public static void main(String[] args) {
+    ExampleChart<BoxPlotChart> exampleChart = new BoxPlotChart03();
+    BoxPlotChart chart = exampleChart.getChart();
+    new SwingWrapper<BoxPlotChart>(chart).displayChart();
+  }
+
+  @Override
+  public BoxPlotChart getChart() {
+
+    // Create Chart
+    BoxPlotChart chart =
+        new BoxPlotChartBuilder()
+        .width(600)
+        .height(450)
+        .title("Y Axis Logarithmic-box plot demo")
+        .xAxisTitle("Color")
+        .yAxisTitle("temperature")
+        .theme(ChartTheme.XChart)
+        .build();
+    // Series
+    BoxPlotSeries[] boxSeries = new BoxPlotSeries[6];
+    boxSeries[0] = chart.addSeries("aaa", Arrays.asList(40, 30, 20, 60, 50));
+    boxSeries[1] = chart.addSeries("bbb", Arrays.asList(20, 10, 25, null, 60));
+    boxSeries[2] = chart.addSeries("ccc", Arrays.asList(30, 20, 22, 40, 50));
+    boxSeries[3] = chart.addSeries("ddd", Arrays.asList(10, 15, 28, 50, 65));
+    boxSeries[4] = chart.addSeries("eee", Arrays.asList(25, 25, 30, 30, 55));
+    boxSeries[5] = chart.addSeries("fff", Arrays.asList(15, 18, 29, 20, 50));
+    // Customize Chart
+    chart.getStyler().setToolTipsEnabled(true);
+    chart.getStyler().setYAxisLogarithmic(true);
+    chart.getStyler().setYAxisMin(1d);
+    chart.getStyler().setYAxisMax(160d);
+    return chart;
+  }
+}
diff --git a/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/pie/PieChart01.java b/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/pie/PieChart01.java
index a69af8e9..7702bff9 100644
--- a/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/pie/PieChart01.java
+++ b/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/pie/PieChart01.java
@@ -4,6 +4,7 @@ import org.knowm.xchart.PieChart;
 import org.knowm.xchart.PieChartBuilder;
 import org.knowm.xchart.SwingWrapper;
 import org.knowm.xchart.demo.charts.ExampleChart;
+import org.knowm.xchart.style.Styler.ChartTheme;
 
 /**
  * Pie Chart with 4 Slices
diff --git a/xchart/src/main/java/org/knowm/xchart/BoxPlotChart.java b/xchart/src/main/java/org/knowm/xchart/BoxPlotChart.java
new file mode 100644
index 00000000..f820c075
--- /dev/null
+++ b/xchart/src/main/java/org/knowm/xchart/BoxPlotChart.java
@@ -0,0 +1,157 @@
+package org.knowm.xchart;
+
+import java.awt.Graphics2D;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.knowm.xchart.internal.Utils;
+import org.knowm.xchart.internal.chartpart.AxisPair;
+import org.knowm.xchart.internal.chartpart.Chart;
+import org.knowm.xchart.internal.chartpart.InfoPanel;
+import org.knowm.xchart.internal.chartpart.Legend_Marker;
+import org.knowm.xchart.internal.chartpart.Plot_BoxPlot;
+import org.knowm.xchart.internal.series.Series.DataType;
+import org.knowm.xchart.internal.style.SeriesColorMarkerLineStyle;
+import org.knowm.xchart.internal.style.SeriesColorMarkerLineStyleCycler;
+import org.knowm.xchart.style.BoxPlotStyler;
+import org.knowm.xchart.style.Styler.ChartTheme;
+import org.knowm.xchart.style.Theme;
+
+public class BoxPlotChart extends Chart<BoxPlotStyler, BoxPlotSeries> {
+
+  private ArrayList xData = new ArrayList();
+  private ArrayList newXData = new ArrayList();
+
+  protected BoxPlotChart(int width, int height) {
+
+    super(width, height, new BoxPlotStyler());
+    axisPair = new AxisPair<BoxPlotStyler, BoxPlotSeries>(this);
+    plot = new Plot_BoxPlot<BoxPlotStyler, BoxPlotSeries>(this);
+    legend = new Legend_Marker<BoxPlotStyler, BoxPlotSeries>(this);
+    infoPanel = new InfoPanel<BoxPlotStyler, BoxPlotSeries>(this);
+  }
+
+  public BoxPlotChart(int width, int height, Theme theme) {
+
+    this(width, height);
+    styler.setTheme(theme);
+  }
+
+  public BoxPlotChart(int width, int height, ChartTheme chartTheme) {
+    this(width, height, chartTheme.newInstance(chartTheme));
+  }
+
+  public BoxPlotChart(BoxPlotChartBuilder chartBuilder) {
+    this(chartBuilder.width, chartBuilder.height, chartBuilder.chartTheme);
+    setTitle(chartBuilder.title);
+    setXAxisTitle(chartBuilder.xAxisTitle);
+    setYAxisTitle(chartBuilder.yAxisTitle);
+  }
+
+  public BoxPlotSeries addSeries(String seriesName, int[] yData) {
+
+    return addSeries(seriesName, Utils.getNumberListFromIntArray(yData));
+  }
+
+  public BoxPlotSeries addSeries(String seriesName, double[] yData) {
+
+    return addSeries(seriesName, Utils.getNumberListFromDoubleArray(yData));
+  }
+
+  public BoxPlotSeries addSeries(String seriesName, List<? extends Number> yData) {
+
+    // Sanity checks
+    sanityCheck(seriesName, yData);
+    BoxPlotSeries series = null;
+    xData.add(seriesName);
+    series = new BoxPlotSeries(seriesName, xData, yData, null, DataType.String);
+    seriesMap.put(seriesName, series);
+    return series;
+  }
+
+  private void sanityCheck(String seriesName, List<? extends Number> yData) {
+
+    if (seriesMap.keySet().contains(seriesName)) {
+      throw new IllegalArgumentException(
+          "Series name > " + seriesName + " < has already been used. Use unique names for each series!!!");
+    }
+    if (yData == null) {
+      throw new IllegalArgumentException("Y-Axis data connot be null !!!");
+    }
+    if (yData.size() == 0) {
+      throw new IllegalArgumentException("Y-Axis data connot be empyt !!!");
+    }
+  }
+
+  public BoxPlotSeries updateBoxSeries(String seriesName, double[] newYData) {
+
+    newXData.add(seriesName);
+    return updateBoxSeries(seriesName, newXData,
+        Utils.getNumberListFromDoubleArray(newYData), Utils.getNumberListFromDoubleArray(null));
+  }
+
+  public BoxPlotSeries updateBoxSeries(String seriesName, List<?> newXData, List<? extends Number> newYData,
+      List<? extends Number> newErrorBarData) {
+
+    Map<String, BoxPlotSeries> seriesMap = getSeriesMap();
+    BoxPlotSeries series = seriesMap.get(seriesName);
+
+    if (series == null) {
+      throw new IllegalArgumentException("Series name > " + seriesName + " < not found !!!");
+    }
+
+    if (newXData == null) {
+      // generate X-Data
+      List<Integer> generatedXData = new ArrayList<Integer>();
+
+      for (int i = 1; i <= newYData.size(); i++) {
+        generatedXData.add(i);
+      }
+      series.replaceData(generatedXData, newYData, newErrorBarData);
+    } else {
+      series.replaceData(newXData, newYData, newErrorBarData);
+    }
+    return series;
+  }
+
+  private void setSeriesStyles() {
+
+    SeriesColorMarkerLineStyleCycler seriesColorMarkerLineStyleCycler = new SeriesColorMarkerLineStyleCycler(
+        getStyler().getSeriesColors(), getStyler().getSeriesMarkers(), getStyler().getSeriesLines());
+    SeriesColorMarkerLineStyle seriesColorMarkerLineStyle = seriesColorMarkerLineStyleCycler
+        .getNextSeriesColorMarkerLineStyle();
+    for (BoxPlotSeries series : getSeriesMap().values()) {
+
+      if (series.getLineStyle() == null) { // wasn't set manually
+        series.setLineStyle(seriesColorMarkerLineStyle.getStroke());
+      }
+      if (series.getLineColor() == null) { // wasn't set manually
+        series.setLineColor(seriesColorMarkerLineStyle.getColor());
+      }
+      if (series.getFillColor() == null) { // wasn't set manually
+        series.setFillColor(seriesColorMarkerLineStyle.getColor());
+      }
+      if (series.getMarker() == null) { // wasn't set manually
+        series.setMarker(seriesColorMarkerLineStyle.getMarker());
+      }
+      if (series.getMarkerColor() == null) { // wasn't set manually
+        series.setMarkerColor(seriesColorMarkerLineStyle.getColor());
+      }
+    }
+  }
+
+  @Override
+  public void paint(Graphics2D g, int width, int height) {
+
+    setWidth(width);
+    setHeight(height);
+    setSeriesStyles();
+    paintBackground(g);
+
+    axisPair.paint(g);
+    plot.paint(g);
+    chartTitle.paint(g);
+    infoPanel.paint(g);
+  }
+}
diff --git a/xchart/src/main/java/org/knowm/xchart/BoxPlotChartBuilder.java b/xchart/src/main/java/org/knowm/xchart/BoxPlotChartBuilder.java
new file mode 100644
index 00000000..9fe95e1c
--- /dev/null
+++ b/xchart/src/main/java/org/knowm/xchart/BoxPlotChartBuilder.java
@@ -0,0 +1,29 @@
+package org.knowm.xchart;
+
+import org.knowm.xchart.internal.ChartBuilder;
+
+public class BoxPlotChartBuilder extends ChartBuilder<BoxPlotChartBuilder, BoxPlotChart> {
+
+  String xAxisTitle = "";
+  String yAxisTitle = "";
+
+  public BoxPlotChartBuilder() {}
+
+  public BoxPlotChartBuilder xAxisTitle(String xAxisTitle) {
+
+    this.xAxisTitle = xAxisTitle;
+    return this;
+  }
+
+  public BoxPlotChartBuilder yAxisTitle(String yAxisTitle) {
+
+    this.yAxisTitle = yAxisTitle;
+    return this;
+  }
+
+  @Override
+  public BoxPlotChart build() {
+
+    return new BoxPlotChart(this);
+  }
+}
diff --git a/xchart/src/main/java/org/knowm/xchart/BoxPlotSeries.java b/xchart/src/main/java/org/knowm/xchart/BoxPlotSeries.java
new file mode 100644
index 00000000..da120223
--- /dev/null
+++ b/xchart/src/main/java/org/knowm/xchart/BoxPlotSeries.java
@@ -0,0 +1,21 @@
+package org.knowm.xchart;
+
+import java.util.List;
+
+import org.knowm.xchart.internal.chartpart.RenderableSeries.LegendRenderType;
+import org.knowm.xchart.internal.series.AxesChartSeriesCategory;
+
+public class BoxPlotSeries extends AxesChartSeriesCategory {
+
+  public BoxPlotSeries(String name, List<?> xData, List<? extends Number> yData, List<? extends Number> extraValues,
+      DataType xAxisDataType) {
+
+    super(name, xData, yData, extraValues, xAxisDataType);
+  }
+
+  @Override
+  public LegendRenderType getLegendRenderType() {
+
+    return null;
+  }
+}
diff --git a/xchart/src/main/java/org/knowm/xchart/internal/chartpart/Axis.java b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/Axis.java
index 40252cf3..7aa2c737 100644
--- a/xchart/src/main/java/org/knowm/xchart/internal/chartpart/Axis.java
+++ b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/Axis.java
@@ -15,6 +15,7 @@ import org.knowm.xchart.internal.series.AxesChartSeriesCategory;
 import org.knowm.xchart.internal.series.Series;
 import org.knowm.xchart.internal.series.Series.DataType;
 import org.knowm.xchart.style.AxesChartStyler;
+import org.knowm.xchart.style.BoxPlotStyler;
 import org.knowm.xchart.style.CategoryStyler;
 import org.knowm.xchart.style.Styler.InfoPanelPosition;
 import org.knowm.xchart.style.Styler.LegendPosition;
@@ -405,7 +406,7 @@ public class Axis<ST extends AxesChartStyler, S extends AxesChartSeries> impleme
     // X-Axis
     if (getDirection() == Direction.X) {
 
-      if (axesChartStyler instanceof CategoryStyler) {
+      if (axesChartStyler instanceof CategoryStyler || axesChartStyler instanceof BoxPlotStyler) {
 
         // TODO Cleanup? More elegant way?
         AxesChartSeriesCategory axesChartSeries =
diff --git a/xchart/src/main/java/org/knowm/xchart/internal/chartpart/AxisPair.java b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/AxisPair.java
index 11b0b3ee..0496cb3f 100644
--- a/xchart/src/main/java/org/knowm/xchart/internal/chartpart/AxisPair.java
+++ b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/AxisPair.java
@@ -9,6 +9,7 @@ import org.knowm.xchart.CategorySeries.CategorySeriesRenderStyle;
 import org.knowm.xchart.internal.series.AxesChartSeries;
 import org.knowm.xchart.internal.series.AxesChartSeriesCategory;
 import org.knowm.xchart.style.AxesChartStyler;
+import org.knowm.xchart.style.BoxPlotStyler;
 import org.knowm.xchart.style.CategoryStyler;
 import org.knowm.xchart.style.Styler.LegendPosition;
 import org.knowm.xchart.style.Styler.YAxisPosition;
@@ -454,18 +455,46 @@ public class AxisPair<ST extends AxesChartStyler, S extends AxesChartSeries> imp
           overrideYAxisMaxValue = 0.0;
         }
       }
+    } else if (chart.getStyler() instanceof BoxPlotStyler) {
+      // the maximum value of the box plot may be greater than all y values, and the
+      // minimum value of the box plot may be less than all y values
+
+      Map<String, S> seriesMap = chart.getSeriesMap();
+      ST boxPlotStyler = chart.getStyler();
+      BoxPlotData<ST, S> boxPlotData = new BoxPlotData<>();
+      int numBoxPlot = seriesMap.size();
+      Double boxPlotYData[][] = new Double[numBoxPlot][BoxPlotData.BOX_DATAS_LENGTH];
+      boxPlotYData = boxPlotData.getBoxPlotData(seriesMap, boxPlotStyler);
+
+      for (int noNumBox = 0; noNumBox < numBoxPlot; noNumBox++) {
+
+        if (boxPlotYData[noNumBox][BoxPlotData.MIN_BOX_VALUE_INDEX] != null && !boxPlotStyler.isYAxisLogarithmic()
+            && overrideYAxisMinValue > boxPlotYData[noNumBox][BoxPlotData.MIN_BOX_VALUE_INDEX]) {
+          overrideYAxisMinValue = boxPlotYData[noNumBox][BoxPlotData.MIN_BOX_VALUE_INDEX];
+        } else if (boxPlotYData[noNumBox][BoxPlotData.MIN_BOX_VALUE_INDEX] != null && boxPlotStyler.isYAxisLogarithmic()
+            && overrideYAxisMinValue > Math.pow(10, boxPlotYData[noNumBox][BoxPlotData.MIN_BOX_VALUE_INDEX])) {
+          overrideYAxisMinValue = Math.pow(10, boxPlotYData[noNumBox][BoxPlotData.MIN_BOX_VALUE_INDEX]);
+        }
+        if (boxPlotYData[noNumBox][BoxPlotData.MAX_BOX_VALUE_INDEX] != null && !boxPlotStyler.isYAxisLogarithmic()
+            && overrideYAxisMaxValue < boxPlotYData[noNumBox][BoxPlotData.MAX_BOX_VALUE_INDEX]) {
+          overrideYAxisMaxValue = boxPlotYData[noNumBox][BoxPlotData.MAX_BOX_VALUE_INDEX];
+        } else if (boxPlotYData[noNumBox][BoxPlotData.MAX_BOX_VALUE_INDEX] != null && boxPlotStyler.isYAxisLogarithmic()
+            && overrideYAxisMaxValue < Math.pow(10, boxPlotYData[noNumBox][BoxPlotData.MAX_BOX_VALUE_INDEX])) {
+          overrideYAxisMaxValue = Math.pow(10, boxPlotYData[noNumBox][BoxPlotData.MAX_BOX_VALUE_INDEX]);
+        }
+      }
     }
 
     // override min and maxValue if specified
     if (chart.getStyler().getYAxisMin(yAxis.getYIndex()) != null) {
       overrideYAxisMinValue = chart.getStyler().getYAxisMin(yAxis.getYIndex());
-    } else if (chart.getStyler().getYAxisMin() != null) {
+    } else if (chart.getStyler().getYAxisMin() != null && !(chart.getStyler() instanceof BoxPlotStyler)) {
       overrideYAxisMinValue = chart.getStyler().getYAxisMin();
     }
 
     if (chart.getStyler().getYAxisMax(yAxis.getYIndex()) != null) {
       overrideYAxisMaxValue = chart.getStyler().getYAxisMax(yAxis.getYIndex());
-    } else if (chart.getStyler().getYAxisMax() != null) {
+    } else if (chart.getStyler().getYAxisMax() != null && !(chart.getStyler() instanceof BoxPlotStyler)) {
       overrideYAxisMaxValue = chart.getStyler().getYAxisMax();
     }
 
diff --git a/xchart/src/main/java/org/knowm/xchart/internal/chartpart/BoxPlotData.java b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/BoxPlotData.java
new file mode 100644
index 00000000..f3d5a011
--- /dev/null
+++ b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/BoxPlotData.java
@@ -0,0 +1,126 @@
+package org.knowm.xchart.internal.chartpart;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.knowm.xchart.internal.series.AxesChartSeries;
+import org.knowm.xchart.internal.series.AxesChartSeriesCategory;
+import org.knowm.xchart.style.AxesChartStyler;
+
+/**
+ * All data used to calculate box plot
+ *
+ */
+public class BoxPlotData<ST extends AxesChartStyler, S extends AxesChartSeries> {
+
+  // Used to store box plot first quartile
+  public final static int FIRST_PLOT_QUARTILES_INDEX = 0;
+  // Used to store box plot second quartile
+  public final static int SECOND_PLOT_QUARTILES_INDEX = 1;
+  // Uesd to store box plot third quartiles
+  public final static int THIRD_PLOT_QUARTILES_INDEX = 2;
+  // Used to store box plot max value
+  public final static int MAX_BOX_VALUE_INDEX = 3;
+  // Uesd to store box plot min value
+  public final static int MIN_BOX_VALUE_INDEX = 4;
+  // Uesd to store box plot average value
+  public final static int AVERAGE_VALUE_INDEX = 5;
+  // Uesd to store the total number of BoxPlots
+  public final static int BOX_DATAS_LENGTH = 6;
+
+  public Double[][] getBoxPlotData(Map<String, S> seriesMap, ST boxPlotStyler) {
+
+    int numBox = seriesMap.size();
+    Double[][] boxPlotYData = new Double[numBox][BOX_DATAS_LENGTH];
+    int yValueIndex = 0;
+    int boxNo = 0;
+
+    for (S series : seriesMap.values()) {
+      if (!series.isEnabled()) {
+        continue;
+      }
+      Collection<? extends Number> yData = ((AxesChartSeriesCategory) series).getYData();
+      Iterator<? extends Number> yItr = yData.iterator();
+      Double[] yValue = new Double[yData.size()];
+      double yTotleValue = 0.0;
+      boolean isNeedToCount = true;
+      yValueIndex = 0;
+
+      while (yItr.hasNext()) {
+        Number next = yItr.next();
+
+        if (next == null) {
+          yValue[yValueIndex] = null;
+          isNeedToCount = false;
+          yValueIndex++;
+          boxNo++;
+          continue;
+        }
+        Double y = next.doubleValue();
+
+        // When the Y-axis logarithm is less than or equal to 0,and no exception is
+        // thrown,skip this point and box
+        if (boxPlotStyler.isYAxisLogarithmic() && y > 0) {
+          y = Math.log10(y);
+        } else if (boxPlotStyler.isYAxisLogarithmic() && y <= 0) {
+          y = null;
+        }
+        yValue[yValueIndex] = y;
+        yValueIndex++;
+        yTotleValue += y;
+      }
+
+      // Box plot seriesMapSize masts greater than 3
+      // When seriesMapSize is less than 3 ,it cannot form a box plot
+      if (yData.size() >= 3 && isNeedToCount) {
+
+        // Box plot all data must be sorted form small to large
+        Arrays.sort(yValue);
+        double firstPlotQuartiles = (yData.size() + 1.0) / 4.0;
+        double secondPlotQuartiles = (yData.size() + 1.0) / 2.0;
+        double thirdPlotQuartiles = 3.0 * (yData.size() + 1.0) / 4.0;
+
+        // When firstPlotQuartiles,secondPlotQuartiles,thirdPlotQuartiles are
+        // integers, the corresponding value is equal to the y value of subscript
+        if (firstPlotQuartiles % 1 == 0) {
+          firstPlotQuartiles = yValue[(int) firstPlotQuartiles - 1];
+        } else {
+          // when When firstPlotQuartiles,secondPlotQuartiles,thirdPlotQuartiles are not
+          // integers, the calculation formula is shown below
+          firstPlotQuartiles = yValue[(int) firstPlotQuartiles - 1]
+              + (yValue[(int) firstPlotQuartiles] - yValue[(int) firstPlotQuartiles - 1]) * (firstPlotQuartiles % 1);
+        }
+        boxPlotYData[boxNo][FIRST_PLOT_QUARTILES_INDEX] = firstPlotQuartiles;
+
+        if (secondPlotQuartiles % 1 == 0) {
+          secondPlotQuartiles = yValue[(int) secondPlotQuartiles - 1];
+        } else {
+          secondPlotQuartiles = yValue[(int) secondPlotQuartiles - 1]
+              + (yValue[(int) secondPlotQuartiles] - yValue[(int) secondPlotQuartiles - 1]) * (secondPlotQuartiles % 1);
+        }
+        boxPlotYData[boxNo][SECOND_PLOT_QUARTILES_INDEX] = secondPlotQuartiles;
+
+        if (thirdPlotQuartiles % 1 == 0) {
+          thirdPlotQuartiles = yValue[(int) thirdPlotQuartiles - 1];
+        } else {
+          thirdPlotQuartiles = yValue[(int) thirdPlotQuartiles - 1]
+              + (yValue[(int) thirdPlotQuartiles] - yValue[(int) thirdPlotQuartiles - 1]) * (thirdPlotQuartiles % 1);
+        }
+        boxPlotYData[boxNo][THIRD_PLOT_QUARTILES_INDEX] = thirdPlotQuartiles;
+        // Box plot max value = thirdPlotQuartiles + 1.5 * (thirdPlotQuartiles -
+        // firstPlotQuartiles)
+        boxPlotYData[boxNo][MAX_BOX_VALUE_INDEX] = thirdPlotQuartiles + 1.5 * (thirdPlotQuartiles - firstPlotQuartiles);
+        // Box plot min value = firstPlotQuartiles - 1.5 * (thirdPlotQuartiles -
+        // firstPlotQuartiles)
+        boxPlotYData[boxNo][MIN_BOX_VALUE_INDEX] = firstPlotQuartiles - 1.5 * (thirdPlotQuartiles - firstPlotQuartiles);
+        // Box plot average
+        boxPlotYData[boxNo][AVERAGE_VALUE_INDEX] = yTotleValue / yData.size();
+        boxNo++;
+      }
+
+    }
+    return boxPlotYData;
+  }
+}
diff --git a/xchart/src/main/java/org/knowm/xchart/internal/chartpart/PlotContent_BoxPlot.java b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/PlotContent_BoxPlot.java
new file mode 100644
index 00000000..a32e208d
--- /dev/null
+++ b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/PlotContent_BoxPlot.java
@@ -0,0 +1,222 @@
+package org.knowm.xchart.internal.chartpart;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.Line2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.knowm.xchart.BoxPlotSeries;
+import org.knowm.xchart.internal.Utils;
+import org.knowm.xchart.style.BoxPlotStyler;
+
+public class PlotContent_BoxPlot<ST extends BoxPlotStyler, S extends BoxPlotSeries> extends PlotContent_<ST, S> {
+
+  private final ST boxPlotStyler;
+  Map<String, S> seriesMap = chart.getSeriesMap();
+  int boxPlotCounter = -1;
+  private double yMax;
+  private double yMin;
+  private double xLeftMargin;
+  private double yTopMargin;
+  private double yTickSpace;
+  private double xOffset;
+  private double yOffset;
+
+  PlotContent_BoxPlot(Chart<ST, S> chart) {
+    super(chart);
+    boxPlotStyler = chart.getStyler();
+  }
+
+  @Override
+  protected void doPaint(Graphics2D g) {
+    int numBox = seriesMap.size();
+    // X-Axis
+    double xTickSpace = boxPlotStyler.getPlotContentSize() * getBounds().getWidth();
+    xLeftMargin = Utils.getTickStartOffset((int) getBounds().getWidth(), xTickSpace);
+    // Y-Axis
+    yTickSpace = boxPlotStyler.getPlotContentSize() * getBounds().getHeight();
+    yTopMargin = Utils.getTickStartOffset((int) getBounds().getHeight(), yTickSpace);
+    boolean toolTipsEnabled = chart.getStyler().isToolTipsEnabled();
+    double gridStep = xTickSpace / numBox;
+    Double[][] boxDatas = new Double[numBox][BoxPlotData.BOX_DATAS_LENGTH];
+    
+
+    // To get all box plot datas
+    BoxPlotData<ST, S> boxPlotData = new BoxPlotData<>();
+    boxDatas = boxPlotData.getBoxPlotData(seriesMap, boxPlotStyler);
+    for (S series : seriesMap.values()) {
+
+      if (!series.isEnabled()) {
+        continue;
+      }
+      String[] toolTips = series.getToolTips();
+      boolean hasCustomToolTips = toolTips != null;
+      Axis yAxis = chart.getYAxis(series.getYAxisGroup());
+      yMin = yAxis.getMin();
+      yMax = yAxis.getMax();
+
+      if (boxPlotStyler.isYAxisLogarithmic()) {
+        yMin = Math.log10(yMin);
+        yMax = Math.log10(yMax);
+      }
+      // data points
+      Collection<? extends Number> yData = series.getYData();
+      double previousX = Double.MAX_VALUE;
+      Iterator<? extends Number> yItr = yData.iterator();
+      Object nextCat = series.getName();
+      Path2D.Double path = null;
+      boxPlotCounter++;
+      while (yItr.hasNext()) {
+
+        Number next = yItr.next();
+
+        if (next == null) {
+          closePath(g, path, previousX, getBounds(), yTopMargin);
+          path = null;
+          previousX = -Double.MAX_VALUE;
+          continue;
+        }
+        double yOrig = next.doubleValue();
+        double y;
+
+        if (boxPlotStyler.isYAxisLogarithmic()) {
+          y = Math.log10(yOrig);
+        } else {
+          y = yOrig;
+        }
+        double yTransfrom = getBounds().getHeight() - (yTopMargin + (y - yMin) / (yMax - yMin) * yTickSpace);
+
+        // a check if all y data are the exact same values
+        if (Math.abs(yMax - yMin) / 5 == 0.0) {
+          yTransfrom = getBounds().getHeight() / 2.0;
+        }
+        xOffset = getBounds().getX() + xLeftMargin + boxPlotCounter * gridStep + gridStep / 2.0;
+        yOffset = getBounds().getY() + yTransfrom;
+
+        // paint marker
+        if (boxDatas[boxPlotCounter][BoxPlotData.MAX_BOX_VALUE_INDEX] != null
+            && (y > boxDatas[boxPlotCounter][BoxPlotData.MAX_BOX_VALUE_INDEX]
+                || y < boxDatas[boxPlotCounter][BoxPlotData.MIN_BOX_VALUE_INDEX])) {
+
+          Shape outPointLine1 = new Line2D.Double(xOffset - boxPlotStyler.getMarkerSize(), yOffset,
+              xOffset + boxPlotStyler.getMarkerSize(), yOffset);
+          Shape outPointLine2 = new Line2D.Double(xOffset, yOffset - boxPlotStyler.getMarkerSize(), xOffset,
+              yOffset + boxPlotStyler.getMarkerSize());
+          g.setColor(Color.RED);
+          g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
+          g.draw(outPointLine1);
+          g.draw(outPointLine2);
+        } else if (chart.getStyler().getShowWithinAreaPoint()) {
+          g.setColor(series.getMarkerColor());
+          series.getMarker().paint(g, xOffset, yOffset, boxPlotStyler.getMarkerSize());
+        }
+        previousX = xOffset;
+
+        // support toolTipsEnabled
+        if (toolTipsEnabled && chart.getStyler().getShowWithinAreaPoint()) {
+          if (hasCustomToolTips) {
+
+            String tt = toolTips[boxPlotCounter];
+            if (tt != null) {
+              chart.toolTips.addData(xOffset, yOffset, tt);
+            }
+          } else {
+            chart.toolTips.addData(xOffset, yOffset, chart.getXAxisFormat().format(nextCat),
+                chart.getYAxisFormat().format(yOrig));
+          }
+        }
+      }
+
+      if (boxDatas[boxPlotCounter][BoxPlotData.FIRST_PLOT_QUARTILES_INDEX] != null) {
+        drawBoxPlot(g, boxDatas, hasCustomToolTips, toolTips, nextCat, toolTipsEnabled);
+      }
+      g.setColor(series.getFillColor());
+      closePath(g, path, previousX, getBounds(), yTopMargin);
+    }
+  }
+
+  private void drawBoxPlot(Graphics2D g, Double boxDatas[][], boolean hasCustomToolTips,
+      String[] toolTips, Object nexCat, boolean toolTipsEnabled) {
+
+    double firstPlotQuartiles = 0.0;
+    double secondPlotQuartiles = 0.0;
+    double thirdPlotQuartiles = 0.0;
+    double maxBoxData = 0.0;
+    double minBoxData = 0.0;
+    firstPlotQuartiles = getBounds().getY() + getBounds().getHeight() - (yTopMargin
+        + (boxDatas[boxPlotCounter][BoxPlotData.FIRST_PLOT_QUARTILES_INDEX] - yMin) / (yMax - yMin) * yTickSpace);
+    secondPlotQuartiles = getBounds().getY() + getBounds().getHeight() - (yTopMargin
+        + (boxDatas[boxPlotCounter][BoxPlotData.SECOND_PLOT_QUARTILES_INDEX] - yMin) / (yMax - yMin) * yTickSpace);
+    thirdPlotQuartiles = getBounds().getY() + getBounds().getHeight() - (yTopMargin
+        + (boxDatas[boxPlotCounter][BoxPlotData.THIRD_PLOT_QUARTILES_INDEX] - yMin) / (yMax - yMin) * yTickSpace);
+    maxBoxData = getBounds().getY() + getBounds().getHeight() - (yTopMargin
+        + (boxDatas[boxPlotCounter][BoxPlotData.MAX_BOX_VALUE_INDEX] - yMin) / (yMax - yMin) * yTickSpace);
+    minBoxData = getBounds().getY() + getBounds().getHeight() - (yTopMargin
+        + (boxDatas[boxPlotCounter][BoxPlotData.MIN_BOX_VALUE_INDEX] - yMin) / (yMax - yMin) * yTickSpace);
+    Shape middleline = new Line2D.Double(xOffset - xLeftMargin, secondPlotQuartiles, xOffset + xLeftMargin,
+        secondPlotQuartiles);
+    Shape maxLine = new Line2D.Double(xOffset - (xLeftMargin / 2.0), maxBoxData, xOffset + (xLeftMargin / 2.0),
+        maxBoxData);
+    Shape minLine = new Line2D.Double(xOffset - (xLeftMargin / 2.0), minBoxData, xOffset + (xLeftMargin / 2.0),
+        minBoxData);
+    Shape upLine = new Line2D.Double(xOffset, maxBoxData, xOffset, thirdPlotQuartiles);
+    Shape lowLine = new Line2D.Double(xOffset, minBoxData, xOffset, firstPlotQuartiles);
+    Rectangle2D rect = new Rectangle2D.Double(xOffset - xLeftMargin, thirdPlotQuartiles, 2.0 * xLeftMargin,
+        firstPlotQuartiles - thirdPlotQuartiles);
+    g.setColor(Color.BLUE);
+    g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
+    g.draw(rect);
+    g.setColor(Color.RED);
+    g.draw(middleline);
+    g.setColor(Color.BLACK);
+    g.draw(maxLine);
+    g.draw(minLine);
+    g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 6.0f, new float[] { 4f, 0f, 4f }, 6f));
+    g.draw(upLine);
+    g.draw(lowLine);
+
+    if (toolTipsEnabled && boxDatas[boxPlotCounter][BoxPlotData.FIRST_PLOT_QUARTILES_INDEX] != null) {
+      if (boxPlotStyler.isYAxisLogarithmic()) {
+        boxDatas[boxPlotCounter][BoxPlotData.FIRST_PLOT_QUARTILES_INDEX] = Math.pow(10,
+            boxDatas[boxPlotCounter][BoxPlotData.FIRST_PLOT_QUARTILES_INDEX]);
+        boxDatas[boxPlotCounter][BoxPlotData.SECOND_PLOT_QUARTILES_INDEX] = Math.pow(10,
+            boxDatas[boxPlotCounter][BoxPlotData.SECOND_PLOT_QUARTILES_INDEX]);
+        boxDatas[boxPlotCounter][BoxPlotData.THIRD_PLOT_QUARTILES_INDEX] = Math.pow(10,
+            boxDatas[boxPlotCounter][BoxPlotData.THIRD_PLOT_QUARTILES_INDEX]);
+        boxDatas[boxPlotCounter][BoxPlotData.MAX_BOX_VALUE_INDEX] = Math.pow(10,
+            boxDatas[boxPlotCounter][BoxPlotData.MAX_BOX_VALUE_INDEX]);
+        boxDatas[boxPlotCounter][BoxPlotData.MIN_BOX_VALUE_INDEX] = Math.pow(10,
+            boxDatas[boxPlotCounter][BoxPlotData.MIN_BOX_VALUE_INDEX]);
+      }
+      if (hasCustomToolTips) {
+
+        String tt = toolTips[boxPlotCounter];
+
+        if (tt != null) {
+          chart.toolTips.addData(xOffset, firstPlotQuartiles, tt);
+          chart.toolTips.addData(xOffset, secondPlotQuartiles, tt);
+          chart.toolTips.addData(xOffset, thirdPlotQuartiles, tt);
+          chart.toolTips.addData(xOffset, maxBoxData, tt);
+          chart.toolTips.addData(xOffset, minBoxData, tt);
+        }
+      } else {
+        chart.toolTips.addData(xOffset, firstPlotQuartiles, chart.getXAxisFormat().format(nexCat),
+            chart.getYAxisFormat().format(boxDatas[boxPlotCounter][BoxPlotData.FIRST_PLOT_QUARTILES_INDEX]));
+        chart.toolTips.addData(xOffset, secondPlotQuartiles, chart.getXAxisFormat().format(nexCat),
+            chart.getYAxisFormat().format(boxDatas[boxPlotCounter][BoxPlotData.SECOND_PLOT_QUARTILES_INDEX]));
+        chart.toolTips.addData(xOffset, thirdPlotQuartiles, chart.getXAxisFormat().format(nexCat),
+            chart.getYAxisFormat().format(boxDatas[boxPlotCounter][BoxPlotData.THIRD_PLOT_QUARTILES_INDEX]));
+        chart.toolTips.addData(xOffset, maxBoxData, chart.getXAxisFormat().format(nexCat),
+            chart.getYAxisFormat().format(boxDatas[boxPlotCounter][BoxPlotData.MAX_BOX_VALUE_INDEX]));
+        chart.toolTips.addData(xOffset, minBoxData, chart.getXAxisFormat().format(nexCat),
+            chart.getYAxisFormat().format(boxDatas[boxPlotCounter][BoxPlotData.MIN_BOX_VALUE_INDEX]));
+      }
+    }
+  }
+}
diff --git a/xchart/src/main/java/org/knowm/xchart/internal/chartpart/Plot_BoxPlot.java b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/Plot_BoxPlot.java
new file mode 100644
index 00000000..3bc4d6b8
--- /dev/null
+++ b/xchart/src/main/java/org/knowm/xchart/internal/chartpart/Plot_BoxPlot.java
@@ -0,0 +1,21 @@
+package org.knowm.xchart.internal.chartpart;
+
+import java.awt.Graphics2D;
+
+import org.knowm.xchart.BoxPlotSeries;
+import org.knowm.xchart.style.BoxPlotStyler;
+
+public class Plot_BoxPlot<ST extends BoxPlotStyler, S extends BoxPlotSeries> extends Plot_AxesChart<ST, S> {
+
+  public Plot_BoxPlot(Chart<ST, S> chart) {
+
+    super(chart);
+  }
+
+  @Override
+  public void paint(Graphics2D g) {
+
+    this.plotContent = new PlotContent_BoxPlot<ST, S>(chart);
+    super.paint(g);
+  }
+}
diff --git a/xchart/src/main/java/org/knowm/xchart/style/BoxPlotStyler.java b/xchart/src/main/java/org/knowm/xchart/style/BoxPlotStyler.java
new file mode 100644
index 00000000..272f9813
--- /dev/null
+++ b/xchart/src/main/java/org/knowm/xchart/style/BoxPlotStyler.java
@@ -0,0 +1,16 @@
+package org.knowm.xchart.style;
+
+public class BoxPlotStyler extends AxesChartStyler {
+
+  public BoxPlotStyler() {
+
+    this.setAllStyles();
+    super.setAllStyles();
+  }
+
+  public void setTheme(Theme theme) {
+
+    this.theme = theme;
+    super.setAllStyles();
+  }
+}
diff --git a/xchart/src/main/java/org/knowm/xchart/style/Styler.java b/xchart/src/main/java/org/knowm/xchart/style/Styler.java
index 88b3df63..7002b226 100644
--- a/xchart/src/main/java/org/knowm/xchart/style/Styler.java
+++ b/xchart/src/main/java/org/knowm/xchart/style/Styler.java
@@ -67,6 +67,8 @@ public abstract class Styler {
   private String decimalPattern;
   private HashMap<Integer, YAxisPosition> yAxisAlignmentMap = new HashMap<Integer, YAxisPosition>();
   private int yAxisLeftWidthHint;
+  // Box plot data ///////////////////////////////
+  private boolean showWithinAreaPoint = false;
 
   void setAllStyles() {
 
@@ -784,6 +786,14 @@ public abstract class Styler {
     this.yAxisLeftWidthHint = yAxisLeftWidthHint;
   }
 
+  public void setShowWithinAreaPoint(boolean showWithinAreaPoint) {
+    this.showWithinAreaPoint = showWithinAreaPoint;
+  }
+
+  public boolean getShowWithinAreaPoint() {
+    return this.showWithinAreaPoint;
+  }
+
   public enum LegendPosition {
     OutsideE,
     InsideNW,


Test patch:
diff --git a/xchart-demo/src/main/java/org/knowm/xchart/demo/ExampleChartTester.java b/xchart-demo/src/main/java/org/knowm/xchart/demo/ExampleChartTester.java
index 4ba3a38b..05146152 100644
--- a/xchart-demo/src/main/java/org/knowm/xchart/demo/ExampleChartTester.java
+++ b/xchart-demo/src/main/java/org/knowm/xchart/demo/ExampleChartTester.java
@@ -40,6 +40,9 @@ import org.knowm.xchart.demo.charts.bar.BarChart09;
 import org.knowm.xchart.demo.charts.bar.BarChart10;
 import org.knowm.xchart.demo.charts.bar.BarChart11;
 import org.knowm.xchart.demo.charts.bar.BarChart12;
+import org.knowm.xchart.demo.charts.boxPlot.BoxPlotChart01;
+import org.knowm.xchart.demo.charts.boxPlot.BoxPlotChart02;
+import org.knowm.xchart.demo.charts.boxPlot.BoxPlotChart03;
 import org.knowm.xchart.demo.charts.bubble.BubbleChart01;
 import org.knowm.xchart.demo.charts.date.DateChart01;
 import org.knowm.xchart.demo.charts.date.DateChart02;
@@ -384,6 +387,11 @@ public class ExampleChartTester extends JPanel implements TreeSelectionListener
     exList.add(new RealtimeChart04());
     exList.add(new RealtimeChart05());
     exList.add(new RealtimeChart06());
+
+    // Box plot
+    exList.add(new BoxPlotChart01());
+    exList.add(new BoxPlotChart02());
+    exList.add(new BoxPlotChart03());
     return exList;
   }