diff --git a/xchart-demo/src/main/java/com/xeiam/xchart/demo/XChartDemo.java b/xchart-demo/src/main/java/com/xeiam/xchart/demo/XChartDemo.java index 25e914d8b4a36c1f2a705c966e41d491e2091e86..4045fb62fe3e306b8df6d38345b71c4015fd3624 100644 --- a/xchart-demo/src/main/java/com/xeiam/xchart/demo/XChartDemo.java +++ b/xchart-demo/src/main/java/com/xeiam/xchart/demo/XChartDemo.java @@ -41,6 +41,7 @@ import com.xeiam.xchart.demo.charts.bar.BarChart04; import com.xeiam.xchart.demo.charts.bar.BarChart05; import com.xeiam.xchart.demo.charts.bar.BarChart06; import com.xeiam.xchart.demo.charts.bar.BarChart07; +import com.xeiam.xchart.demo.charts.bar.BarChart08; import com.xeiam.xchart.demo.charts.date.DateChart01; import com.xeiam.xchart.demo.charts.date.DateChart02; import com.xeiam.xchart.demo.charts.date.DateChart03; @@ -261,6 +262,9 @@ public class XChartDemo extends JPanel implements TreeSelectionListener { defaultMutableTreeNode = new DefaultMutableTreeNode(new ChartInfo("BarChart07 - Histogram Not Overlapped", new BarChart07().getChart())); category.add(defaultMutableTreeNode); + defaultMutableTreeNode = new DefaultMutableTreeNode(new ChartInfo("BarChart08 - Histogram with Error Bars", new BarChart08().getChart())); + category.add(defaultMutableTreeNode); + // Theme category category = new DefaultMutableTreeNode("Chart Themes"); top.add(category); diff --git a/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/bar/BarChart08.java b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/bar/BarChart08.java new file mode 100644 index 0000000000000000000000000000000000000000..a2d717aefdc4dd2889d8704222014e17ff8b014e --- /dev/null +++ b/xchart-demo/src/main/java/com/xeiam/xchart/demo/charts/bar/BarChart08.java @@ -0,0 +1,83 @@ +/** + * Copyright 2011 - 2014 Xeiam LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.xeiam.xchart.demo.charts.bar; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import com.xeiam.xchart.Chart; +import com.xeiam.xchart.ChartBuilder; +import com.xeiam.xchart.Histogram; +import com.xeiam.xchart.StyleManager.ChartType; +import com.xeiam.xchart.StyleManager.LegendPosition; +import com.xeiam.xchart.SwingWrapper; +import com.xeiam.xchart.demo.charts.ExampleChart; + +/** + * Histogram with Error Bars + * <p> + * Demonstrates the following: + * <ul> + * <li>Histogram + * <li>Bar Chart with error bars + */ +public class BarChart08 implements ExampleChart { + + public static void main(String[] args) { + + ExampleChart exampleChart = new BarChart08(); + Chart chart = exampleChart.getChart(); + new SwingWrapper(chart).displayChart(); + } + + @Override + public Chart getChart() { + + // Create Chart + Chart chart = new ChartBuilder().chartType(ChartType.Bar).width(800).height(600).title("Histogram").xAxisTitle("Mean").yAxisTitle("Count").build(); + + Histogram histogram1 = new Histogram(getGaussianData(10000), 10, -10, 10); + chart.addSeries("histogram", histogram1.getxAxisData(), histogram1.getyAxisData(), getFakeErrorData(histogram1.getxAxisData().size())); + + // Customize Chart + chart.getStyleManager().setLegendPosition(LegendPosition.InsideNW); + chart.getStyleManager().setBarWidthPercentage(.96); + + return chart; + } + + private List<Double> getGaussianData(int count) { + + List<Double> data = new ArrayList<Double>(count); + Random r = new Random(); + for (int i = 0; i < count; i++) { + data.add(r.nextGaussian() * 5); + // data.add(r.nextDouble() * 60 - 30); + } + return data; + } + + private List<Double> getFakeErrorData(int count) { + + List<Double> data = new ArrayList<Double>(count); + Random r = new Random(); + for (int i = 0; i < count; i++) { + data.add(r.nextDouble() * 200); + } + return data; + } +} diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/PlotContentBarChart.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/PlotContentBarChart.java index 6ee673bdc1a24d37e79bf606de58b0f2989ee4b4..7b497463f1c8dfeb9fa1c620f1ab5751ebfe994e 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/PlotContentBarChart.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/PlotContentBarChart.java @@ -17,6 +17,8 @@ package com.xeiam.xchart.internal.chartpart; import java.awt.Graphics2D; import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.Line2D; import java.awt.geom.Path2D; import java.awt.geom.Rectangle2D; import java.util.Collection; @@ -122,6 +124,11 @@ public class PlotContentBarChart extends PlotContent { // all the x-axis data are guaranteed to be the same so we just use the first one Iterator<? extends Number> yItr = yData.iterator(); + Iterator<? extends Number> ebItr = null; + Collection<? extends Number> errorBars = series.getErrorBars(); + if (errorBars != null) { + ebItr = errorBars.iterator(); + } int barCounter = 0; while (yItr.hasNext()) { @@ -210,6 +217,41 @@ public class PlotContentBarChart extends PlotContent { g.draw(path); } + // paint errorbars + + if (errorBars != null) { + + double eb = ebItr.next().doubleValue(); + + // set error bar style + if (getChartPainter().getStyleManager().isErrorBarsColorSeriesColor()) { + g.setColor(series.getStrokeColor()); + } + else { + g.setColor(getChartPainter().getStyleManager().getErrorBarsColor()); + } + g.setStroke(errorBarStroke); + + // Top value + double topValue = y + eb; + double topEBTransform = bounds.getHeight() - (yTopMargin + (topValue - yMin) / (yMax - yMin) * yTickSpace); + double topEBOffset = bounds.getY() + topEBTransform; + + // Bottom value + double bottomValue = y - eb; + double bottomEBTransform = bounds.getHeight() - (yTopMargin + (bottomValue - yMin) / (yMax - yMin) * yTickSpace); + double bottomEBOffset = bounds.getY() + bottomEBTransform; + + // Draw it + double errorBarOffset = xOffset + barWidth / 2; + Shape line = new Line2D.Double(errorBarOffset, topEBOffset, errorBarOffset, bottomEBOffset); + g.draw(line); + line = new Line2D.Double(errorBarOffset - 3, bottomEBOffset, errorBarOffset + 3, bottomEBOffset); + g.draw(line); + line = new Line2D.Double(errorBarOffset - 3, topEBOffset, errorBarOffset + 3, topEBOffset); + g.draw(line); + } + } seriesCounter++; } diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/PlotContentLineChart.java b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/PlotContentLineChart.java index bcf987e834df3149b3072cc1b1481438c0cc3f95..ec65b7de2e856adfb4b0cd438bc0c76b10048f17 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/PlotContentLineChart.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/chartpart/PlotContentLineChart.java @@ -114,7 +114,6 @@ public class PlotContentLineChart extends PlotContent { yMin = Math.log10(yMin); yMax = Math.log10(yMax); } - Collection<? extends Number> errorBars = series.getErrorBars(); double previousX = Integer.MIN_VALUE; double previousY = Integer.MIN_VALUE; @@ -122,6 +121,7 @@ public class PlotContentLineChart extends PlotContent { Iterator<?> xItr = xData.iterator(); Iterator<? extends Number> yItr = yData.iterator(); Iterator<? extends Number> ebItr = null; + Collection<? extends Number> errorBars = series.getErrorBars(); if (errorBars != null) { ebItr = errorBars.iterator(); } @@ -227,17 +227,11 @@ public class PlotContentLineChart extends PlotContent { } // paint errorbars - - double eb = 0.0; - - if (errorBars != null) { - eb = ebItr.next().doubleValue(); - } - if (errorBars != null) { - // set error bar color + double eb = ebItr.next().doubleValue(); + // set error bar style if (getChartPainter().getStyleManager().isErrorBarsColorSeriesColor()) { g.setColor(series.getStrokeColor()); } @@ -246,6 +240,7 @@ public class PlotContentLineChart extends PlotContent { } g.setStroke(errorBarStroke); + // Top value double topValue = 0.0; if (getChartPainter().getStyleManager().isYAxisLogarithmic()) { topValue = yOrig + eb; @@ -257,6 +252,7 @@ public class PlotContentLineChart extends PlotContent { double topEBTransform = bounds.getHeight() - (yTopMargin + (topValue - yMin) / (yMax - yMin) * yTickSpace); double topEBOffset = bounds.getY() + topEBTransform; + // Bottom value double bottomValue = 0.0; if (getChartPainter().getStyleManager().isYAxisLogarithmic()) { bottomValue = yOrig - eb; @@ -269,6 +265,7 @@ public class PlotContentLineChart extends PlotContent { double bottomEBTransform = bounds.getHeight() - (yTopMargin + (bottomValue - yMin) / (yMax - yMin) * yTickSpace); double bottomEBOffset = bounds.getY() + bottomEBTransform; + // Draw it Shape line = new Line2D.Double(xOffset, topEBOffset, xOffset, bottomEBOffset); g.draw(line); line = new Line2D.Double(xOffset - 3, bottomEBOffset, xOffset + 3, bottomEBOffset); diff --git a/xchart/src/main/java/com/xeiam/xchart/internal/style/XChartTheme.java b/xchart/src/main/java/com/xeiam/xchart/internal/style/XChartTheme.java index d09084da2a277f2c8217c3f52bef5212d4d882ea..b03db2b063adc9201db330fcf054f2902c2950d5 100644 --- a/xchart/src/main/java/com/xeiam/xchart/internal/style/XChartTheme.java +++ b/xchart/src/main/java/com/xeiam/xchart/internal/style/XChartTheme.java @@ -312,7 +312,7 @@ public class XChartTheme implements Theme { @Override public Color getErrorBarsColor() { - return ChartColor.getAWTColor(ChartColor.DARK_GREY); + return ChartColor.getAWTColor(ChartColor.BLACK); } @Override