JFreeChart BarChart invertierte anzeige oder werte bereich von-bis

  • Themenstarter Themenstarter An!ma
  • Beginndatum Beginndatum
A

An!ma

Gast
Hallo Forum =)

bin nun schon seid tagen damit beschäftigt mit JFreeChart ein paar Diagramme zu erstellen. Das klappt soweit auch ganz gut nur nun habe ich ein Problem das sich weder per google, noch FAQ, noch durch die Foren suche lösen lassen will.

Ich möchte ein invertiertes Diagramm erzeugen.
Dazu nutze ich
Java:
rangeAxis.setInverted(true);

Nun ist die Y-Achse auch invertiert (wie gewünscht) nur hab ich jetzt das Problem das die Balken von oben nach unten gehen. Und eben das soll nicht passieren.

Kennt ihr eine Möglichkeit einen Balken im BarChart erst ab einem bestimmten Punkt zu zeichnen?
Bzw. nen Wertebereich fest zu legen, der dann gefüllt werden soll?
 
was heißt denn 'invertierte Anzeige' bei dir, was genau ist dein Ziel?
nehme ich ein Standard-Beispiel wie
JFreeChart: Bar Chart Demo : Bar ChartChartJava
und setze invertiert, dann gehen die Balken freilich nach unten, was denn sonst?

sind aber alle Werte negativ, dann wieder Balken von 0 nach oben, hin zu -1, -2, -3 usw.,
du kannst kaum erwarten dass JFreeChart mal eben alles als negativ annimmt,
das kannst du doch über die Eingabe steuern, übergib negative Werte wenn das dein Ziel ist

für Wertebereich gibt es Standardmöglichkeiten
java - Setting Range for X,Y Axis-JfreeChart - Stack Overflow
 
hmm hmm,
meines Wissens überfordert das die Möglichkeiten des Standards

gewisse eher unsaubere Überschreibungen der API-Klassen gibts aber noch als Strohhalm
java - How can I change the tickLabel on a NumberAxis in JFreeChart? - Stack Overflow

hier eine Variante, die jeden Wert x als 4-x ausgibt:

die lange Methode createStandardTickUnits() ist eine Kopie des Originals (je nach Version vielleicht nicht ganz aktuell),
alle NumberTickUnit sind durch NumberTickUnitX ersetzt,
wenn man den Wertebereich kennt braucht man nicht unbedingt alle der TickUnit, sie schaden aber auch nicht als allgemein verwendbar


Java:
public class BarChartDemo
    extends ApplicationFrame
{

    /**
     * Creates a new demo instance.
     * 
     * @param title
     *            the frame title.
     */
    public BarChartDemo(final String title)
    {

        super(title);

        final CategoryDataset dataset = createDataset();
        final JFreeChart chart = createChart(dataset);
        final ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new Dimension(500, 270));
        setContentPane(chartPanel);

    }

    /**
     * Returns a sample dataset.
     * 
     * @return The dataset.
     */
    private CategoryDataset createDataset()
    {

        // row keys...
        final String series1 = "First";
        final String series2 = "Second";
        final String series3 = "Third";

        // column keys...
        final String category1 = "Category 1";
        final String category2 = "Category 2";
        final String category3 = "Category 3";
        final String category4 = "Category 4";
        final String category5 = "Category 5";

        // create the dataset...
        final DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        dataset.addValue(1.0, series1, category1);
        dataset.addValue(4.0, series1, category2);
        dataset.addValue(3.0, series1, category3);
        dataset.addValue(5.0, series1, category4);
        dataset.addValue(5.0, series1, category5);

        dataset.addValue(5.0, series2, category1);
        dataset.addValue(7.0, series2, category2);
        dataset.addValue(6.0, series2, category3);
        dataset.addValue(8.0, series2, category4);
        dataset.addValue(4.0, series2, category5);

        dataset.addValue(4.0, series3, category1);
        dataset.addValue(3.0, series3, category2);
        dataset.addValue(2.0, series3, category3);
        dataset.addValue(3.0, series3, category4);
        dataset.addValue(6.0, series3, category5);

        return dataset;

    }

    /**
     * Creates a sample chart.
     * 
     * @param dataset
     *            the dataset.
     * 
     * @return The chart.
     */
    private JFreeChart createChart(final CategoryDataset dataset)
    {

        // create the chart...
        final JFreeChart chart = ChartFactory.createBarChart("Bar Chart Demo", // chart
                                                                               // title
                                                             "Category", // domain axis
                                                                         // label
                                                             "Value", // range axis label
                                                             dataset, // data
                                                             PlotOrientation.VERTICAL, // orientation
                                                             true, // include legend
                                                             true, // tooltips?
                                                             false // URLs?
        );

        // NOW DO SOME OPTIONAL CUSTOMISATION OF THE CHART...

        // set the background color for the chart...
        chart.setBackgroundPaint(Color.white);

        // get a reference to the plot for further customisation...
        final CategoryPlot plot = chart.getCategoryPlot();
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);

        // set the range axis to display integers only...
        final NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(createStandardTickUnits());

        // disable bar outlines...
        final BarRenderer renderer = (BarRenderer)plot.getRenderer();
        renderer.setDrawBarOutline(false);

        // set up gradient paints for series...
        final GradientPaint gp0 = new GradientPaint(0.0f, 0.0f, Color.blue, 0.0f, 0.0f, Color.lightGray);
        final GradientPaint gp1 = new GradientPaint(0.0f, 0.0f, Color.green, 0.0f, 0.0f, Color.lightGray);
        final GradientPaint gp2 = new GradientPaint(0.0f, 0.0f, Color.red, 0.0f, 0.0f, Color.lightGray);
        renderer.setSeriesPaint(0, gp0);
        renderer.setSeriesPaint(1, gp1);
        renderer.setSeriesPaint(2, gp2);

        final CategoryAxis domainAxis = plot.getDomainAxis();
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 6.0));
        // OPTIONAL CUSTOMISATION COMPLETED.

        return chart;

    }

    // ****************************************************************************
    // * JFREECHART DEVELOPER GUIDE *
    // * The JFreeChart Developer Guide, written by David Gilbert, is available *
    // * to purchase from Object Refinery Limited: *
    // * *
    // * [url=http://www.object-refinery.com/jfreechart/guide.html]Object Refinery Limited - JFreeChart[/url] *
    // * *
    // * Sales are used to provide funding for the JFreeChart project - please *
    // * support us so that we can continue developing free software. *
    // ****************************************************************************

    /**
     * Starting point for the demonstration application.
     * 
     * @param args
     *            ignored.
     */
    public static void main(final String[] args)
    {

        final BarChartDemo demo = new BarChartDemo("Bar Chart Demo");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);

    }

    public static TickUnitSource createStandardTickUnits()
    {

        TickUnits units = new TickUnits();
        DecimalFormat df0 = new DecimalFormat("0.00000000");
        DecimalFormat df1 = new DecimalFormat("0.0000000");
        DecimalFormat df2 = new DecimalFormat("0.000000");
        DecimalFormat df3 = new DecimalFormat("0.00000");
        DecimalFormat df4 = new DecimalFormat("0.0000");
        DecimalFormat df5 = new DecimalFormat("0.000");
        DecimalFormat df6 = new DecimalFormat("0.00");
        DecimalFormat df7 = new DecimalFormat("0.0");
        DecimalFormat df8 = new DecimalFormat("#,##0");
        DecimalFormat df9 = new DecimalFormat("#,###,##0");
        DecimalFormat df10 = new DecimalFormat("#,###,###,##0");

        // we can add the units in any order, the TickUnits collection will
        // sort them...
        units.add(new NumberTickUnitX(0.0000001, df1));
        units.add(new NumberTickUnitX(0.000001, df2));
        units.add(new NumberTickUnitX(0.00001, df3));
        units.add(new NumberTickUnitX(0.0001, df4));
        units.add(new NumberTickUnitX(0.001, df5));
        units.add(new NumberTickUnitX(0.01, df6));
        units.add(new NumberTickUnitX(0.1, df7));
        units.add(new NumberTickUnitX(1, df8));
        units.add(new NumberTickUnitX(10, df8));
        units.add(new NumberTickUnitX(100, df8));
        units.add(new NumberTickUnitX(1000, df8));
        units.add(new NumberTickUnitX(10000, df8));
        units.add(new NumberTickUnitX(100000, df8));
        units.add(new NumberTickUnitX(1000000, df9));
        units.add(new NumberTickUnitX(10000000, df9));
        units.add(new NumberTickUnitX(100000000, df9));
        units.add(new NumberTickUnitX(1000000000, df10));
        units.add(new NumberTickUnitX(10000000000.0, df10));
        units.add(new NumberTickUnitX(100000000000.0, df10));

        units.add(new NumberTickUnitX(0.00000025, df0));
        units.add(new NumberTickUnitX(0.0000025, df1));
        units.add(new NumberTickUnitX(0.000025, df2));
        units.add(new NumberTickUnitX(0.00025, df3));
        units.add(new NumberTickUnitX(0.0025, df4));
        units.add(new NumberTickUnitX(0.025, df5));
        units.add(new NumberTickUnitX(0.25, df6));
        units.add(new NumberTickUnitX(2.5, df7));
        units.add(new NumberTickUnitX(25, df8));
        units.add(new NumberTickUnitX(250, df8));
        units.add(new NumberTickUnitX(2500, df8));
        units.add(new NumberTickUnitX(25000, df8));
        units.add(new NumberTickUnitX(250000, df8));
        units.add(new NumberTickUnitX(2500000, df9));
        units.add(new NumberTickUnitX(25000000, df9));
        units.add(new NumberTickUnitX(250000000, df9));
        units.add(new NumberTickUnitX(2500000000.0, df10));
        units.add(new NumberTickUnitX(25000000000.0, df10));
        units.add(new NumberTickUnitX(250000000000.0, df10));

        units.add(new NumberTickUnitX(0.0000005, df1));
        units.add(new NumberTickUnitX(0.000005, df2));
        units.add(new NumberTickUnitX(0.00005, df3));
        units.add(new NumberTickUnitX(0.0005, df4));
        units.add(new NumberTickUnitX(0.005, df5));
        units.add(new NumberTickUnitX(0.05, df6));
        units.add(new NumberTickUnitX(0.5, df7));
        units.add(new NumberTickUnitX(5L, df8));
        units.add(new NumberTickUnitX(50L, df8));
        units.add(new NumberTickUnitX(500L, df8));
        units.add(new NumberTickUnitX(5000L, df8));
        units.add(new NumberTickUnitX(50000L, df8));
        units.add(new NumberTickUnitX(500000L, df8));
        units.add(new NumberTickUnitX(5000000L, df9));
        units.add(new NumberTickUnitX(50000000L, df9));
        units.add(new NumberTickUnitX(500000000L, df9));
        units.add(new NumberTickUnitX(5000000000L, df10));
        units.add(new NumberTickUnitX(50000000000L, df10));
        units.add(new NumberTickUnitX(500000000000L, df10));

        return units;

    }

    static class NumberTickUnitX     extends NumberTickUnit   {

        public NumberTickUnitX(double _size, NumberFormat _formatter)
        {
            super(_size, _formatter);
        }

        /**
         * @inheritDoc
         */
        @Override
        public String valueToString(double _value)
        {
            return super.valueToString(4 - _value);
        }

    }
}

edit, Zusatz:
etwas kürzer wäre wohl, im Standard-TickUnits die vorhandenden TickUnit zu durchlaufen,
das private NumberFormat-Feld per Reflection zu ersetzen, falls erlaubt,

oder ein eigenes TickUnits zu erzeugen und die vorhandenen Units zu wrappen, so läuft es bei mir auch:
Java:
public static TickUnitSource createStandardTickUnits()
    {
        TickUnits def = (TickUnits)NumberAxis.createStandardTickUnits();
        TickUnits units = new TickUnits();
        for (int i = 0; i < def.size(); i++)
        {
            TickUnit u = def.get(i);
            units.add(new NumberTickUnitX(u));
        }
        return units;

    }

    static class NumberTickUnitX
        extends NumberTickUnit
    {
        TickUnit u;

        public NumberTickUnitX(TickUnit u)
        {
            super(0);
            this.u = u;
        }

        @Override
        public int compareTo(Object _arg0)
        {
            return this.u.compareTo(_arg0);
        }

        @Override
        public double getSize()
        {
            return this.u.getSize();
        }

        @Override
        public String valueToString(double _value)
        {
            return this.u.valueToString(4 - _value);
        }

    }
 
Zuletzt bearbeitet von einem Moderator:
Danke für deine Hilfe, funktioniert wunderbar.
Da ich mich in einem Zahlenraum von 1 bis 4 bewege konnte ich den QC noch etwas verkürzen.

Java:
    public static TickUnitSource createStandardTickUnits()
    {
 
        TickUnits units = new TickUnits();
        DecimalFormat df1 = new DecimalFormat("#,##0");
        units.add(new NumberTickUnitX(1, df1));
        return units;
 
    }
 
    static class NumberTickUnitX     extends NumberTickUnit   {
 
        public NumberTickUnitX(double _size, NumberFormat _formatter)
        {
            super(_size, _formatter);
        }
 
        /**
         * @inheritDoc
         */
        @Override
        public String valueToString(double _value)
        {
            return super.valueToString(4 - _value);
        }
 
    }


Und das ist nun das Ergebnis

imgimg.de - Dein Bilderhoster zum Bilder hochladen - final586399dbPNG.png

Problem solved!
 

Zurück
Oben