Wie lässt sich ein Flächendiagramm erstellen?
Das Beispiel zeigt das Flächendiagramms eines fiktiven Gasverbrauchs in den Jahren 2020 und 2021. Für jeden Monat ist die jeweilige Menge des Verbrauchs notiert.
Die X-Achse wird zur Erfassung des Zeitstrahls durch ein
Objekt der Klasse CategoryAxis
, die Y-Achse
zur Darstellung der Mengen als NumberAxis
realisiert. Eine CategoryAxis
kann
beliebige Wertebezeichner als Strings darstellen, eine NumberAxis
visualisiert immer einen linearen numerischen Verlauf
beginnend bei einem unteren und endend bei einem oberen
Wert. Für beide Achsen wird mittles setLabel()
die Anzeige der Dimension initiiert. Bei der Erzeugung
der AreaChart
werden beide Axis
-Objekte
dem Konstruktor als Argumente übergeben.
Die
Methode setCreateSymbols(false)
bewirkt
dann, dass die oberen Grenzlinien der
Diagrammflächen ohne eine gesonderte Markierung der
Datenpunkte gezeichnet wird. Wird hier true
übergeben oder verzichtet man auf den
Methodenaufruf, so werden an den Datenpunkten, wie bei Liniendiagrammen
auch, Marker in Form kleiner Kreise dargestellt. Ein Beispiel hierzu findet sich im Abschnitt über negative
Werte.
Für jedes Jahr wird eine Datengruppe vom Typ XYChart.Series
erstellt. Sie speichert die Verbrauchswerte in Form
mehrerer XYChart.Data
-Objekte. Hierbei
werden in jedem jeweils der String des Monatsnamens und
der Verbrauch in diesem Zeitraum gespeichert. Die Werte
werden dem Konstruktor übergeben.
Im Einzelnen
geschieht dies so, dass durch getData()
die
ObservableList
des Series
-Objektes
ermittelt und dieser dann durch add()
das Data
-Objekt
übergeben wird. Auf diese Weise werden die Werte
für jedes Jahr in einer separaten Liste abgelegt.
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.AreaChart; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.StackedAreaChart; import javafx.scene.chart.XYChart; import javafx.stage.Stage; public class AreaChartBsp extends Application { @Override public void start(Stage stage) { stage.setTitle("Area Chart Beispiel"); final CategoryAxis xAxis = new CategoryAxis(); final NumberAxis yAxis = new NumberAxis(); xAxis.setLabel("Monat"); yAxis.setLabel("Menge [m\u00b3]"); final AreaChart<String, Number> ac = new AreaChart<>(xAxis,yAxis); ac.setCreateSymbols(false); ac.setTitle("Gasverbrauch [m\u00b3]"); XYChart.Series series20= new XYChart.Series(); series20.setName("2020"); series20.getData().add(new XYChart.Data("Januar", 129)); series20.getData().add(new XYChart.Data("Februar", 88)); series20.getData().add(new XYChart.Data("M\u00e4rz", 69)); series20.getData().add(new XYChart.Data("April", 15)); series20.getData().add(new XYChart.Data("Mai", 3)); series20.getData().add(new XYChart.Data("Juni", 1)); series20.getData().add(new XYChart.Data("Juli", 0)); series20.getData().add(new XYChart.Data("August", 0)); series20.getData().add(new XYChart.Data("September", 0)); series20.getData().add(new XYChart.Data("Oktober", 42)); series20.getData().add(new XYChart.Data("November", 69)); series20.getData().add(new XYChart.Data("Dezember", 133)); XYChart.Series series21 = new XYChart.Series(); series21.setName("2021"); series21.getData().add(new XYChart.Data("Januar", 162)); series21.getData().add(new XYChart.Data("Februar", 105)); series21.getData().add(new XYChart.Data("M\u00e4rz", 71)); series21.getData().add(new XYChart.Data("April", 39)); series21.getData().add(new XYChart.Data("Mai", 0)); series21.getData().add(new XYChart.Data("Juni", 0)); series21.getData().add(new XYChart.Data("Juli", 1)); series21.getData().add(new XYChart.Data("August", 0)); series21.getData().add(new XYChart.Data("September", 0)); series21.getData().add(new XYChart.Data("Oktober", 27)); series21.getData().add(new XYChart.Data("November", 90)); series21.getData().add(new XYChart.Data("Dezember", 111)); Scene scene = new Scene(ac,800,600); ac.getData().addAll(series20, series21); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
Das AreaChart
-Objekt stellt ebenfalls eine
ObservableList
bereit. Ihr werden in Zeile
54 durch addAll()
die einzelnen Gruppen
übergeben. Ohne zusätzliche
Formatierung bestimmt die hier verwendete
Reihenfolge die Einfärbung der Kurven.
Negative Werte
Die angegebenen Werte bestimmen im Standardfall den
Darstellungsbereich des Diagramms. Will man diesen
ändern, so besteht die Möglichkeit, dem
Konstruktor einer NumberAxis
den unteren
und oberen Grenzwert, sowie die Schrittweite anzugeben.
Die o.a. Abbildung ist somit äquivalent zum
Konstruktoraufruf
NumberAxis yAxis = new NumberAxis(0, 170, 10);
Eine nachträgliche Änderung kann durch Aufrufe
der Methoden setLowerBound(double d),
setUpperBound(double d)
und setTickUnit(double d)
erfolgen.
Möchte man z.B. den 0-Wert nicht auf
der Höhe der Y-Achse liegen haben, so ist dies
durch die Erweiterung des Anzeigebereiches durch
negative Werte möglich.
NumberAxis yAxis = new NumberAxis(-20, 170, 10);
Umfasst der Bereich der übergebenen Daten den
negativen Bereich, so erweitert sich die Darstellung im
Standardfall automatisch. Das folgende Beispiel
illustriert dies anhand von Abweichungen von einem
Mittelwert. Soll die automatische Bereichserfassung
unterbunden werden, so kann dies durch Aufruf der
Methode setAutoRanging(false)
erfolgen.
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.AreaChart; import javafx.scene.chart.CategoryAxis; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.StackedAreaChart; import javafx.scene.chart.XYChart; import javafx.scene.chart.XYChart.Series; import javafx.stage.Stage; public class AreaChartBsp2 extends Application { @SuppressWarnings("unchecked") @Override public void start(Stage stage) { stage.setTitle("Area Chart Beispiel"); final CategoryAxis xAxis = new CategoryAxis(); final NumberAxis yAxis = new NumberAxis(); xAxis.setLabel("Monat"); yAxis.setLabel("Abweichung vom monatl.Durchschnitt [m\u00b3]"); final AreaChart<String ,Number> ac = new AreaChart<>(xAxis,yAxis); ac.setTitle("Gasverbrauch [m\u00b3]"); XYChart.Series series20= new XYChart.Series(); series20.setName("2020"); series20.getData().add(new XYChart.Data("Januar", computeFromAverage(50.5, 129))); series20.getData().add(new XYChart.Data("Februar", computeFromAverage(50.5, 88))); series20.getData().add(new XYChart.Data("M\u00e4rz", computeFromAverage(50.5, 69))); series20.getData().add(new XYChart.Data("April", computeFromAverage(50.5, 15))); series20.getData().add(new XYChart.Data("Mai", computeFromAverage(50.5, 3))); series20.getData().add(new XYChart.Data("Juni", computeFromAverage(50.5, 1))); series20.getData().add(new XYChart.Data("Juli", computeFromAverage(50.5, 0))); series20.getData().add(new XYChart.Data("August", computeFromAverage(50.5, 0))); series20.getData().add(new XYChart.Data("September", computeFromAverage(50.5, 0))); series20.getData().add(new XYChart.Data("Oktober", computeFromAverage(50.5, 42))); series20.getData().add(new XYChart.Data("November", computeFromAverage(50.5, 69))); series20.getData().add(new XYChart.Data("Dezember", computeFromAverage(50.5, 133))); Scene scene = new Scene(ac,800,600); String stylesheet = getClass().getResource("/styles/areaChartStyles.css").toExternalForm(); scene.getStylesheets().add(stylesheet); ac.getData().addAll(series20); stage.setScene(scene); stage.show(); } private double computeFromAverage(double av, double value) { return value - av; } public static void main(String[] args) { launch(args); } }
In Zeile 40 und 41 wird ein Stylesheet geladen, in dem
über den Selektor .chart-horizontal-zero-line
die Farbe der 0-Linie geändert wurde.
.chart-horizontal-zero-line { -fx-stroke: #dddddd; }
Quellen
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.