Wie lässt sich ein Liniendiagramm erstellen?
Das Beispiel demonstriert das Zeichnen eines Liniendiagramms, in dem die Anzahl der errungenen Zweitstimmen einiger Parteien bei den Bundestagswahlen von 1980 bis 2021 dargestellt werden[1]. Die X-Achse repräsentiert die Zeitachse, die Y-Achse gibt den Stimmenanteil in Prozent an.
Beide Achsen werden durch Objekte der Klasse NumberAxis
realisiert und mit einem Labeltext zur Bezeichnung der
jeweils erfassten Größe versehen. Sie werden
dem Konstruktor bei der Erzeugung der LineChart
übergeben. Da auf beiden Achsen numerische Werte
aufgetragen werden, müssen dem generischen Typ LineChart
beide Datentypen als Number
bekanntgemacht
werden.
Für jede Partei wird eine Datengruppe vom Typ XYChart.Series
erstellt. Sie speichert die Werte in Form mehrerer XYChart.Data
-Objekte.
In jedem werden jeweils ein Wahljahr und der bei dieser
Wahl erreichte Stimmenanteil 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 jede Partei in einer separaten Liste abgelegt.
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.chart.LineChart; import javafx.scene.chart.NumberAxis; import javafx.scene.chart.XYChart; import javafx.stage.Stage; public class LineChartBsp extends Application { @SuppressWarnings({ "unchecked" }) @Override public void start(Stage stage) { stage.setTitle("Line Chart Beispiel"); final NumberAxis xAxis = new NumberAxis(1980, 2022, 1); final NumberAxis yAxis = new NumberAxis(); xAxis.setLabel("Jahr"); yAxis.setLabel("Stimmenanteil [%]"); LineChart<Number,Number> lineChart = new LineChart<Number,Number>(xAxis, yAxis); lineChart.setTitle("Bundestagswahlen"); XYChart.Series<Number, Number> seriesCdu = new XYChart.Series<Number, Number>(); seriesCdu.setName("CDU/CSU"); seriesCdu.getData().add(new XYChart.Data<Number, Number>(1980, 44.5)); seriesCdu.getData().add(new XYChart.Data<Number, Number>(1983, 48.8)); seriesCdu.getData().add(new XYChart.Data<Number, Number>(1987, 44.3)); seriesCdu.getData().add(new XYChart.Data<Number, Number>(1990, 43.8)); seriesCdu.getData().add(new XYChart.Data<Number, Number>(1994, 41.4)); seriesCdu.getData().add(new XYChart.Data<Number, Number>(1998, 35.1)); seriesCdu.getData().add(new XYChart.Data<Number, Number>(2002, 38.5)); seriesCdu.getData().add(new XYChart.Data<Number, Number>(2005, 35.2)); seriesCdu.getData().add(new XYChart.Data<Number, Number>(2009, 33.8)); seriesCdu.getData().add(new XYChart.Data<Number, Number>(2013, 41.5)); seriesCdu.getData().add(new XYChart.Data<Number, Number>(2017, 32.9)); seriesCdu.getData().add(new XYChart.Data<Number, Number>(2021, 24.1)); XYChart.Series<Number, Number> seriesSpd = new XYChart.Series<Number, Number>(); seriesSpd.setName("SPD"); seriesSpd.getData().add(new XYChart.Data<Number, Number>(1980, 42.9)); seriesSpd.getData().add(new XYChart.Data<Number, Number>(1983, 38.8)); seriesSpd.getData().add(new XYChart.Data<Number, Number>(1987, 37.0)); seriesSpd.getData().add(new XYChart.Data<Number, Number>(1990, 33.5)); seriesSpd.getData().add(new XYChart.Data<Number, Number>(1994, 36.4)); seriesSpd.getData().add(new XYChart.Data<Number, Number>(1998, 40.9)); seriesSpd.getData().add(new XYChart.Data<Number, Number>(2002, 38.5)); seriesSpd.getData().add(new XYChart.Data<Number, Number>(2005, 34.2)); seriesSpd.getData().add(new XYChart.Data<Number, Number>(2009, 23.0)); seriesSpd.getData().add(new XYChart.Data<Number, Number>(2013, 25.7)); seriesSpd.getData().add(new XYChart.Data<Number, Number>(2017, 20.5)); seriesSpd.getData().add(new XYChart.Data<Number, Number>(2021, 25.7)); XYChart.Series<Number, Number> seriesGruen = new XYChart.Series<Number, Number>(); seriesGruen.setName("Gr\u00fcne"); seriesGruen.getData().add(new XYChart.Data<Number, Number>(1980, 1.5)); seriesGruen.getData().add(new XYChart.Data<Number, Number>(1983, 5.6)); seriesGruen.getData().add(new XYChart.Data<Number, Number>(1987, 8.3)); seriesGruen.getData().add(new XYChart.Data<Number, Number>(1990, 5.1)); seriesGruen.getData().add(new XYChart.Data<Number, Number>(1994, 7.3)); seriesGruen.getData().add(new XYChart.Data<Number, Number>(1998, 8.7)); seriesGruen.getData().add(new XYChart.Data<Number, Number>(2002, 8.6)); seriesGruen.getData().add(new XYChart.Data<Number, Number>(2005, 8.1)); seriesGruen.getData().add(new XYChart.Data<Number, Number>(2009, 10.7)); seriesGruen.getData().add(new XYChart.Data<Number, Number>(2013, 8.4)); seriesGruen.getData().add(new XYChart.Data<Number, Number>(2017, 8.9)); seriesGruen.getData().add(new XYChart.Data<Number, Number>(2021, 14.8)); XYChart.Series<Number, Number> seriesFdp = new XYChart.Series<Number, Number>(); seriesFdp.setName("FDP"); seriesFdp.getData().add(new XYChart.Data<Number, Number>(1980, 10.6)); seriesFdp.getData().add(new XYChart.Data<Number, Number>(1983, 7.0)); seriesFdp.getData().add(new XYChart.Data<Number, Number>(1987, 9.1)); seriesFdp.getData().add(new XYChart.Data<Number, Number>(1990, 11.0)); seriesFdp.getData().add(new XYChart.Data<Number, Number>(1994, 6.9)); seriesFdp.getData().add(new XYChart.Data<Number, Number>(1998, 6.2)); seriesFdp.getData().add(new XYChart.Data<Number, Number>(2002, 7.4)); seriesFdp.getData().add(new XYChart.Data<Number, Number>(2005, 9.8)); seriesFdp.getData().add(new XYChart.Data<Number, Number>(2009, 14.6)); seriesFdp.getData().add(new XYChart.Data<Number, Number>(2013, 4.8)); seriesFdp.getData().add(new XYChart.Data<Number, Number>(2017, 10.7)); seriesFdp.getData().add(new XYChart.Data<Number, Number>(2021, 11.5)); XYChart.Series<Number, Number> seriesAfd = new XYChart.Series<Number, Number>(); seriesAfd.setName("AFD"); seriesAfd.getData().add(new XYChart.Data<Number, Number>(1980, 0)); seriesAfd.getData().add(new XYChart.Data<Number, Number>(1983, 0)); seriesAfd.getData().add(new XYChart.Data<Number, Number>(1987, 0)); seriesAfd.getData().add(new XYChart.Data<Number, Number>(1990, 0)); seriesAfd.getData().add(new XYChart.Data<Number, Number>(1994, 0)); seriesAfd.getData().add(new XYChart.Data<Number, Number>(1998, 0)); seriesAfd.getData().add(new XYChart.Data<Number, Number>(2002, 0)); seriesAfd.getData().add(new XYChart.Data<Number, Number>(2005, 0)); seriesAfd.getData().add(new XYChart.Data<Number, Number>(2009, 0)); seriesAfd.getData().add(new XYChart.Data<Number, Number>(2013, 4.7)); seriesAfd.getData().add(new XYChart.Data<Number, Number>(2017, 12.6)); seriesAfd.getData().add(new XYChart.Data<Number, Number>(2021, 10.3)); XYChart.Series<Number, Number> seriesLinke = new XYChart.Series<Number, Number>(); seriesLinke.setName("Die Linke"); seriesLinke.getData().add(new XYChart.Data<Number, Number>(1980, 0)); seriesLinke.getData().add(new XYChart.Data<Number, Number>(1983, 0)); seriesLinke.getData().add(new XYChart.Data<Number, Number>(1987, 0)); seriesLinke.getData().add(new XYChart.Data<Number, Number>(1990, 2.4)); seriesLinke.getData().add(new XYChart.Data<Number, Number>(1994, 4.4)); seriesLinke.getData().add(new XYChart.Data<Number, Number>(1998, 5.1)); seriesLinke.getData().add(new XYChart.Data<Number, Number>(2002, 4.0)); seriesLinke.getData().add(new XYChart.Data<Number, Number>(2005, 8.7)); seriesLinke.getData().add(new XYChart.Data<Number, Number>(2009, 11.9)); seriesLinke.getData().add(new XYChart.Data<Number, Number>(2013, 8.6)); seriesLinke.getData().add(new XYChart.Data<Number, Number>(2017, 9.2)); seriesLinke.getData().add(new XYChart.Data<Number, Number>(2021, 4.9)); Scene scene = new Scene(lineChart,800,600); String stylesheet = getClass().getResource("/styles/styles.css").toExternalForm(); scene.getStylesheets().add(stylesheet); lineChart.getData().addAll(seriesSpd, seriesFdp, seriesGruen, seriesCdu, seriesAfd, seriesLinke); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
Das LineChart
-Objekt stellt ebenfalls eine
ObservableList
bereit. Ihr werden in Zeile
114 die einzelnen Gruppen übergeben.
Im Diagramm werden die einzelnen Datenpunkte durch
kleine Kreise dargestellt. Möchte man diese vermeiden,
so kann dies durch Aufruf von lineChart.setCreateSymbols(false);
erfolgen.
Farbkonfiguration
Die Farbe, in der die einzelnen Gruppen im Diagramm
dargestellt werden, wird durch das
JavaFX-Default-Stylesheet1
gesteuert. Die Zuweisung der Farben kann hierbei durch
die Reihenfolge bei der Parameterübergabe an die
Methode addAll()
(Zeile 114) gesteuert
werden. Sollen wie im vorliegenden Fall auch eigene
Farben Verwendung finden, können diese durch
Überschreiben der Stylesheets gesetzt werden.
Hierzu werden diese in den Zeilen 112 und 113 aus einer
Datei geladen und an die Scene
übergeben.
/* Kreise und Legende */ .default-color3.chart-line-symbol { -fx-background-color: #000000, white; } .default-color4.chart-line-symbol { -fx-background-color: #aa5030, white; } /* Linie */ .default-color3.chart-series-line { -fx-stroke: #000000; } .default-color4.chart-series-line { -fx-stroke: #aa5030; } /* Hintergrund */ .chart-plot-background, .chart, .chart-legend { -fx-background-color: #bbb; }
Im Beispiel findet die Einfärbung der als 4. und 5.
Gruppe (AFD, CDU) geladenen Elemente statt. Die
verwendeten Selektoren .default-colorX.chart-line-symbol
und .default-colorX.chart-series-line
beziehen sich auf die kleinen Kreise in Diagramm und
Legende, sowie auf die Linie selbst. Das X muss
jeweils durch die Position in der Ladereihenfolge
beginnend bei 0 ersetzt werden. Auf diese Weise ist eine
Vergabe von acht verschiedenen Farben möglich.
Quellen
1) Das Default-Stylesheet findet sich
unter dem Pfad jfxrt.jar/com/sun/javafx/scene/control/skin/caspian/caspian.css
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.