# JFreeChart Balkenanordnung



## LukeVlbg (29. Sep 2009)

Mal wieder ein Chart Problem. Ich würde gerne 2 Balken nebeneinander anordnen.
Im Moment ist es so, dass die Balken übereinander liegen (Abbildung 1).

Sie sollten aber - so sein wie in Abbildung 2 - nebeneinander anderordnet werden.


----------



## SlaterB (29. Sep 2009)

wie kamst du denn zu dem zweiten Bild, manuell gemalt oder inzwischen vergessene Einstellungen?
wenn du für beides je ein Testprogramm hast und ungefähr erklären kannst warum die zwei Balken nicht mehr da sind, könnte ich noch versuchen, paar Einstellungen zu ändern,
sonst von mir keine Idee

Bar ChartChartJava
sind Balken nebeneinander nicht der Standard?


----------



## LukeVlbg (29. Sep 2009)

Das 2. Bild ist in BIRT geschrieben, ich kenne die Sourcen aber nicht. Ich sollte hier BIRT durch JFreeChart ersetzen. Also ich hab nur das Bild.
Ich dachte auch dass die Balken standardmäßig, wenn man sie auf die gleiche Kategorie setzt, nebeneinander angeordnet sein sollten.

Das ist mein aktueller Code:


```
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.text.DecimalFormat;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.axis.TickUnits;
import org.jfree.chart.block.BlockBorder;
import org.jfree.chart.block.ColumnArrangement;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import org.jfree.ui.TextAnchor;


public class LineBarOverlaidNew extends ApplicationFrame {
	
	/**
	 * Serial version UID
	 */
	private static final long serialVersionUID = 1L;

	public LineBarOverlaidNew(final String title) {
		super(title);
		
		// Erstellen des ersten Datasets (Bar-Chart)
		DefaultCategoryDataset dataset = new DefaultCategoryDataset();
		dataset.addValue(6, "Rückmeldungen", "Di, 2009-07-28");
		dataset.addValue(0, "Rückmeldungen", "Mi, 2009-07-29");
		dataset.addValue(0, "Rückmeldungen", "Do, 2009-07-30");
		dataset.addValue(0, "Rückmeldungen", "Fr, 2009-07-31");
		dataset.addValue(0, "Rückmeldungen", "Sa, 2009-08-01");
		dataset.addValue(0, "Rückmeldungen", "So, 2009-08-02");
		dataset.addValue(0, "Rückmeldungen", "Mo, 2009-08-03");
		dataset.addValue(0, "Rückmeldungen", "Di, 2009-08-04");
		dataset.addValue(0, "Rückmeldungen", "Mi, 2009-08-05");
		dataset.addValue(0, "Rückmeldungen", "Do, 2009-08-06");
		dataset.addValue(0, "Rückmeldungen", "Fr, 2009-08-07");
		dataset.addValue(0, "Rückmeldungen", "Sa, 2009-08-08");
		dataset.addValue(0, "Rückmeldungen", "So, 2009-08-09");
		dataset.addValue(40, "Rückmeldungen", "Mo, 2009-08-10");
		dataset.addValue(48, "Rückmeldungen", "Di, 2009-08-11");
		dataset.addValue(51, "Rückmeldungen", "Mi, 2009-08-12");
		dataset.addValue(64, "Rückmeldungen", "Do, 2009-08-13");
		dataset.addValue(78, "Rückmeldungen", "Fr, 2009-08-14");
		dataset.addValue(23, "Rückmeldungen", "Sa, 2009-08-15");
		dataset.addValue(0, "Rückmeldungen", "So, 2009-08-16");
		dataset.addValue(88, "Rückmeldungen", "Mo, 2009-08-17");
		
		final BarRenderer renderer = new BarRenderer();
		renderer.setMaximumBarWidth(0.01);
//		DecimalFormat decimalformat1 = new DecimalFormat("#,###,###,##0.###########");
		//DecimalFormat decimalformat = new DecimalFormat(Constants.DEFAULT_DECIMALFORMAT_DOUBLE_SEPERATOR_STRING);
//		renderer.setItemLabelGenerator(new StandardCategoryItemLabelGenerator("{2}", decimalformat1));
//		renderer.setItemLabelsVisible(true);
		renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
//        renderer.setBaseItemLabelsVisible(true);
        renderer.setBaseItemLabelFont(new Font("Tahoma", Font.PLAIN, 12));
		renderer.setItemLabelAnchorOffset(8);
		renderer.setSeriesPaint(0, new Color(0, 141, 188));
//		renderer.setDrawBarOutline(true);
		renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, 
				TextAnchor.BASELINE_LEFT, TextAnchor.BASELINE_LEFT, (45.0/180.0) * -Math.PI));
		
//		renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, 
//				TextAnchor.BASELINE_LEFT, TextAnchor.BASELINE_LEFT, -1.0471975511965976));
		
		DefaultCategoryDataset dataset4 = new DefaultCategoryDataset();
		dataset4.addValue(5, "Rückmeldungen", "Di, 2009-07-28");
		dataset4.addValue(0, "Rückmeldungen", "Mi, 2009-07-29");
		dataset4.addValue(0, "Rückmeldungen", "Do, 2009-07-30");
		dataset4.addValue(0, "Rückmeldungen", "Fr, 2009-07-31");
		dataset4.addValue(0, "Rückmeldungen", "Sa, 2009-08-01");
		dataset4.addValue(0, "Rückmeldungen", "So, 2009-08-02");
		dataset4.addValue(0, "Rückmeldungen", "Mo, 2009-08-03");
		dataset4.addValue(0, "Rückmeldungen", "Di, 2009-08-04");
		dataset4.addValue(0, "Rückmeldungen", "Mi, 2009-08-05");
		dataset4.addValue(0, "Rückmeldungen", "Do, 2009-08-06");
		dataset4.addValue(0, "Rückmeldungen", "Fr, 2009-08-07");
		dataset4.addValue(0, "Rückmeldungen", "Sa, 2009-08-08");
		dataset4.addValue(0, "Rückmeldungen", "So, 2009-08-09");
		dataset4.addValue(36, "Rückmeldungen", "Mo, 2009-08-10");
		dataset4.addValue(35, "Rückmeldungen", "Di, 2009-08-11");
		dataset4.addValue(52, "Rückmeldungen", "Mi, 2009-08-12");
		dataset4.addValue(60, "Rückmeldungen", "Do, 2009-08-13");
		dataset4.addValue(60, "Rückmeldungen", "Fr, 2009-08-14");
		dataset4.addValue(20, "Rückmeldungen", "Sa, 2009-08-15");
		dataset4.addValue(0, "Rückmeldungen", "So, 2009-08-16");
		dataset4.addValue(86, "Rückmeldungen", "Mo, 2009-08-17");
		
		final BarRenderer renderer4 = new BarRenderer();
		renderer4.setMaximumBarWidth(0.01);
//		DecimalFormat decimalformat1 = new DecimalFormat("#,###,###,##0.###########");
		//DecimalFormat decimalformat = new DecimalFormat(Constants.DEFAULT_DECIMALFORMAT_DOUBLE_SEPERATOR_STRING);
//		renderer.setItemLabelGenerator(new StandardCategoryItemLabelGenerator("{2}", decimalformat1));
//		renderer4.setItemLabelsVisible(true);
		renderer4.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
//        renderer4.setBaseItemLabelsVisible(true);
        renderer4.setBaseItemLabelFont(new Font("Tahoma", Font.PLAIN, 12));
		renderer4.setItemLabelAnchorOffset(8);
		renderer4.setSeriesPaint(0, new Color(245, 70, 0));
		
		final CategoryPlot plot = new CategoryPlot();
		plot.setDataset(0, dataset);
		plot.setRenderer(0, renderer);
		plot.setDataset(1, dataset4);
		plot.setRenderer(1, renderer4);
		
		renderer.setBarPainter(new StandardBarPainter());
		renderer.setShadowVisible(false);
		renderer.setBaseOutlinePaint(Color.BLACK);
		renderer4.setBarPainter(new StandardBarPainter());
		renderer4.setShadowVisible(false);
		renderer4.setBaseOutlinePaint(Color.BLACK);
		
		plot.setDomainAxis(new CategoryAxis("Datum"));
		plot.setRangeAxis(new NumberAxis("Stunden"));
		plot.getDomainAxis().setLabelFont(new Font("Tahoma", Font.BOLD, 14));
		plot.getRangeAxis().setLabelFont(new Font("Tahoma", Font.BOLD, 14));
		
		/* Skalierung manuell anpassen */
		DecimalFormat decimalformat = new DecimalFormat("#,###,###,##0.###########");
		TickUnits units = new TickUnits();
		units.add(new NumberTickUnit(10, decimalformat));
		plot.getRangeAxis().setStandardTickUnits(units);
		
		plot.setOrientation(PlotOrientation.VERTICAL);
		plot.setRangeGridlinesVisible(false);
		plot.setDomainGridlinesVisible(false);
		plot.setOutlineVisible(false);			// Rahmen ausschalten
		
		// Erstellen des zweiten Datasets - Line-Chart: Blaue Linie
		DefaultCategoryDataset dataset2 = new DefaultCategoryDataset();
		
		dataset2.addValue(28, "Durchschnitt", "Di, 2009-07-28");
		dataset2.addValue(28, "Durchschnitt", "Mi, 2009-07-29");
		dataset2.addValue(28, "Durchschnitt", "Do, 2009-07-30");
		dataset2.addValue(28, "Durchschnitt", "Fr, 2009-07-31");
		dataset2.addValue(28, "Durchschnitt", "Sa, 2009-08-01");
		dataset2.addValue(28, "Durchschnitt", "So, 2009-08-02");
		dataset2.addValue(28, "Durchschnitt", "Mo, 2009-08-03");
		dataset2.addValue(28, "Durchschnitt", "Di, 2009-08-04");
		dataset2.addValue(28, "Durchschnitt", "Mi, 2009-08-05");
		dataset2.addValue(28, "Durchschnitt", "Do, 2009-08-06");
		dataset2.addValue(28, "Durchschnitt", "Fr, 2009-08-07");
		dataset2.addValue(28, "Durchschnitt", "Sa, 2009-08-08");
		dataset2.addValue(28, "Durchschnitt", "So, 2009-08-09");
		dataset2.addValue(28, "Durchschnitt", "Mo, 2009-08-10");
		dataset2.addValue(28, "Durchschnitt", "Di, 2009-08-11");
		dataset2.addValue(28, "Durchschnitt", "Mi, 2009-08-12");
		dataset2.addValue(28, "Durchschnitt", "Do, 2009-08-13");
		dataset2.addValue(28, "Durchschnitt", "Fr, 2009-08-14");
		dataset2.addValue(28, "Durchschnitt", "Sa, 2009-08-15");
		dataset2.addValue(28, "Durchschnitt", "So, 2009-08-16");
		dataset2.addValue(28, "Durchschnitt", "Mo, 2009-08-17");

		// Erstellen des dritten Datasets - Line-Chart: Orange Linie
		DefaultCategoryDataset dataset3 = new DefaultCategoryDataset();
		dataset3.addValue(60, "Plankapazität", "Di, 2009-07-28");
		dataset3.addValue(60, "Plankapazität", "Mi, 2009-07-29");
		dataset3.addValue(60, "Plankapazität", "Do, 2009-07-30");
		dataset3.addValue(60, "Plankapazität", "Fr, 2009-07-31");
		dataset3.addValue(0, "Plankapazität", "Sa, 2009-08-01");
		dataset3.addValue(0, "Plankapazität", "So, 2009-08-02");
		dataset3.addValue(60, "Plankapazität", "Mo, 2009-08-03");
		dataset3.addValue(60, "Plankapazität", "Di, 2009-08-04");
		dataset3.addValue(60, "Plankapazität", "Mi, 2009-08-05");
		dataset3.addValue(60, "Plankapazität", "Do, 2009-08-06");
		dataset3.addValue(60, "Plankapazität", "Fr, 2009-08-07");
		dataset3.addValue(0, "Plankapazität", "Sa, 2009-08-08");
		dataset3.addValue(0, "Plankapazität", "So, 2009-08-09");
		dataset3.addValue(40.57, "Plankapazität", "Mo, 2009-08-10");
		dataset3.addValue(40.57, "Plankapazität", "Di, 2009-08-11");
		dataset3.addValue(40.57, "Plankapazität", "Mi, 2009-08-12");
		dataset3.addValue(40.57, "Plankapazität", "Do, 2009-08-13");
		dataset3.addValue(40.57, "Plankapazität", "Fr, 2009-08-14");
		dataset3.addValue(0, "Plankapazität", "Sa, 2009-08-15");
		dataset3.addValue(0, "Plankapazität", "So, 2009-08-16");
		dataset3.addValue(82, "Plankapazität", "Mo, 2009-08-17");

		final LineAndShapeRenderer renderer2 = new LineAndShapeRenderer();
		
		renderer2.setSeriesPaint(0, Color.BLUE);
		renderer2.setShapesVisible(false);
		plot.setDataset(2, dataset2);
		plot.setRenderer(2, renderer2);
		renderer2.setSeriesStroke(0, new BasicStroke(2));
		
        plot.setDataset(3, dataset3);
        final LineAndShapeRenderer renderer3 = new LineAndShapeRenderer();
        plot.setRenderer(3, renderer3);
        renderer3.setShapesVisible(false);
        renderer3.setSeriesPaint(0, new Color(245, 70, 0));
        renderer3.setSeriesStroke(0, new BasicStroke(2));

        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
        
        plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_90);
        plot.getRangeAxis().setRange(0, 120); // legt Größe der Y-Achse fest (min, max)
        plot.getDomainAxis().setTickLabelFont(new Font("Tahoma", Font.PLAIN, 13));
        plot.getRangeAxis().setTickLabelFont(new Font("Tahoma", Font.PLAIN, 13));
        plot.getRangeAxis().setUpperMargin(5.5);
        
        final JFreeChart chart = new JFreeChart("", new Font("Tahoma", Font.BOLD, 16), plot, true);
        chart.setTitle("Rückmeldungen für Arbeitsplatz 330301 FLACHSCHL.MITTEL");
        chart.getLegend().setFrame(BlockBorder.NONE);
        chart.setBackgroundPaint(Color.WHITE);
        
        LegendTitle legendTitle = chart.getLegend();
        LegendTitle legendTitleNew = new LegendTitle(plot, new ColumnArrangement(), new ColumnArrangement());
        legendTitleNew.setPosition(legendTitle.getPosition());
        legendTitleNew.setBackgroundPaint(legendTitle.getBackgroundPaint());
        legendTitleNew.setBorder(legendTitle.getBorder());
        
        chart.removeLegend();
        chart.addLegend(legendTitleNew);
        
        final ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new Dimension(870, 400));
        setContentPane(chartPanel);
        chartPanel.setRangeZoomable(false);
        
	}
	
	public static void main(String args[]) {
		
		final LineBarOverlaidNew overlaid = new LineBarOverlaidNew("Line- and Barchart overlaid");
		overlaid.pack();
		RefineryUtilities.centerFrameOnScreen(overlaid);
		overlaid.setVisible(true);
	}
}
```


----------



## SlaterB (29. Sep 2009)

schön langes Beispiel, 25 Elemente und jede einzelne gesetzte Schriftart sind ja wichtig 

allgemein ist es eher so gedacht, dass ein DataSet mehrere Kategorien enthält,
du hast mehrere DataSet mit je einer Kategorie, bisher habe ich dazu nix gefunden,

ein Trick wäre noch, in dem zweiten DataSet Dummy-Werte einzutragen, um dort mehrere Kategorien zu bilden,
kannst schauen ob du damit zurecht kommst


```
public class LineBarOverlaidNew
    extends ApplicationFrame
{
    public LineBarOverlaidNew()
    {
        super("");

        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        dataset.addValue(78, "Rückmeldungen", "Fr, 2009-08-14");
        dataset.addValue(23, "Rückmeldungen", "Sa, 2009-08-15");
        dataset.addValue(70, "Rückmeldungen", "So, 2009-08-16");
        dataset.addValue(48, "Rückmeldungen", "Mo, 2009-08-17");

        final BarRenderer renderer = new BarRenderer();
        renderer.setMaximumBarWidth(0.01);

        DefaultCategoryDataset dataset4 = new DefaultCategoryDataset();
        dataset4.addValue(0, "Rückmeldungen", "Fr, 2009-08-14");
        dataset4.addValue(0, "Rückmeldungen", "Sa, 2009-08-15");
        dataset4.addValue(0, "Rückmeldungen", "So, 2009-08-16");
        dataset4.addValue(0, "Rückmeldungen", "Mo, 2009-08-17");
        dataset4.addValue(60, "Rückmeldungen2", "Fr, 2009-08-14");
        dataset4.addValue(20, "Rückmeldungen2", "Sa, 2009-08-15");
        dataset4.addValue(10, "Rückmeldungen2", "So, 2009-08-16");
        dataset4.addValue(86, "Rückmeldungen2", "Mo, 2009-08-17");

        final BarRenderer renderer4 = new BarRenderer();
        renderer4.setMaximumBarWidth(0.01);
        renderer4.setSeriesPaint(0, new Color(245, 170, 220));

        final CategoryPlot plot = new CategoryPlot();
        plot.setDataset(0, dataset);
        plot.setRenderer(0, renderer);
        plot.setDataset(1, dataset4);
        plot.setRenderer(1, renderer4);

        plot.setDomainAxis(new CategoryAxis("Datum"));
        plot.setRangeAxis(new NumberAxis("Stunden"));
        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);

        final JFreeChart chart = new JFreeChart("", null, plot, true);
        final ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new Dimension(870, 400));
        setContentPane(chartPanel);
        chartPanel.setRangeZoomable(false);
    }

    public static void main(String args[])
    {
        final LineBarOverlaidNew overlaid = new LineBarOverlaidNew();
        overlaid.pack();
        RefineryUtilities.centerFrameOnScreen(overlaid);
        overlaid.setVisible(true);
    }
}
```


----------



## LukeVlbg (29. Sep 2009)

Klär mich auf wenn ich falsch liege, aber sind nicht "Fr,...", "Sa,..." usw. die Kategorien und "Rückmeldungen" die Serie.

```
dataset.addValue(int value, String series, String category)
```

Von dem Stand bin ich ausgegangen.


----------



## SlaterB (29. Sep 2009)

na dann sind mehrere Balken standardmäßig eben mehrere Serien in einem DataSet 
jedenfalls liegt das Problem bei den mehreren DataSets vs. normalerweise ein DataSet, das ist der Punkt

da kommst wohl nicht drumherum, das sehe ich schon ein, falls nicht ein DataSet reicht und man für jede Serien einen Renderer angeben kann


----------



## LukeVlbg (29. Sep 2009)

Ich versteht nur bahnhof aus deiner erklärung


----------



## SlaterB (29. Sep 2009)

JFreeChart: Bar Chart Demo : Bar ChartChartJava
da gehts, da ist nur ein DataSet

bei dir gehts nicht, weil mehrere DataSets


----------



## LukeVlbg (12. Okt 2009)

Gut, ich habs jetzt mit einem Dataset für alle Bars und für die Linien eigene Datasets, geregelt. Funktioniert soweit ganz gut.

Wie bekomme ich jetzt aber zwischen die Balken (also zwischen den Kategorien) einen Abstand hinein? Weil sonst erkennt man gar nicht welche Balken zusammengehören.

Lg


----------



## SlaterB (12. Okt 2009)

da kenne ich persönlich nichts zu

schau dir alle noch verfügbaren Methoden an, etwa 
setItemMargin(double percent) in BarRenderer,

vielleicht ist das aber auch eher was für den Plot, weil viele Renderer betroffen sind


----------



## LukeVlbg (12. Okt 2009)

SetItemMargin(double) ist *exakt* das was ich gesucht habe. Vielen Dank!

Jetzt sieht das ganze so aus:


----------

