Een van de belangrijkste aspecten van rapportage is om de inhoud zo goed mogelijk zichtbaar te maken, zodat de essentie van de informatie in het rapport zijn publiek snel en moeiteloos bereikt. Grafieken spelen daarbij een cruciale rol. Het presenteren van onbewerkte gegevens en het proberen zich het scenario voor te stellen dat aan de gegevens is gekoppeld, is niet erg eenvoudig, maar grafieken vertegenwoordigen een picturale essentie van de gegevens en helpen de kijker het idee achter de ruwe gegevens zeer snel te begrijpen. JavaFX heeft ingebouwde ondersteuning om ruwe gegevens dynamisch in pittoreske vorm te presenteren. De API heeft twee facetten:men kan ofwel de API-klassen uitbreiden en een geheel nieuwe grafiek maken, of de beschikbare grafiekspecifieke klassen gebruiken om een grafiek te maken met zeer minimale code. Dit artikel gaat in op de belangrijkste aspecten van de grafiek-API's van JavaFX en laat zien hoe u deze kunt implementeren. Er worden snelle voorbeelden gegeven om u te helpen.
JavaFX-grafieken
JavaFX-diagrammen zijn niet alleen eenvoudig te integreren met andere delen van de applicatie, maar zijn ook opgenomen in het uitbreidbare beleid van objectgeoriënteerde technologie die kan worden aangepast aan de behoefte van de ontwikkelaar. Dit is niet nieuw, omdat objectgeoriënteerde ontwerpen altijd bedoeld zijn om uitbreidbaar te zijn, maar het interessante aan de JavaFX-kaart-API is dat er veel kant-en-klare grafiekklassen zijn die kunnen worden geïnstantieerd met een kleine of geen verandering in de eigenschappen om professioneel ogende grafieken te krijgen. Deze grafiekklassen zijn het meest gebruikelijk, aanpasbaar en voldoen aan bijna elke behoefte van de ontwikkelaar. In de meeste gevallen is het nauwelijks nodig om helemaal opnieuw een aangepast diagram te maken.
JavaFX biedt acht van dergelijke soorten grafieken in de API-bibliotheek met hun ingebouwde functionaliteit. Hoewel er veel ondersteunende klassen en interfaces zijn in de JavaFX-kaart-API-bibliotheek, is de implementatie van de concrete acht als volgt hiërarchisch gerangschikt.
Figuur 1: Het JavaFX-diagram API-bibliotheekhiërarchiediagram
Daarom zijn de acht meest voorkomende soorten diagrammen:cirkeldiagram , staafdiagram , vlakdiagram , lijndiagram , spreidingsdiagram , bubbelgrafiek , gestapeld vlakdiagram , en gestapeld staafdiagram .
Het cirkeldiagram
Het cirkeldiagram is een veelgebruikt diagramformaat waarin informatie wordt weergegeven in een typische cirkelvormige structuur. Elke taartschijf vertegenwoordigt de proportionele waarde van de gegevens. De eenvoudigste manier om een cirkeldiagram in JavaFX te maken, is door het PieChart te instantiëren class en stel de gegevens als volgt in:
PieChart pie=new PieChart();
We kunnen de gegevens voor een cirkeldiagram instellen met behulp van de setData() methode, die een parameter van het type ObservableList
PieChart.Data(String title, Double value)
Hier is een snel voorbeeld om een cirkeldiagram te maken.
package org.mano.example; import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.chart.PieChart; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { stage.setTitle("JavaFX Chart Demo"); StackPane pane = new StackPane(); pane.getChildren().add(createPieChart()); stage.setScene(new Scene(pane, 400, 200)); stage.show(); } public PieChart createPieChart() { PieChart pie = new PieChart(); ObservableList<PieChart.Data> data = FXCollections.observableArrayList(); data.addAll(new PieChart.Data("Asia", 30.0), new PieChart.Data("Africa", 20.3), new PieChart.Data("North America", 16.3), new PieChart.Data("South America", 12.0), new PieChart.Data("Antartica", 8.9), new PieChart.Data("Europe", 6.7), new PieChart.Data("Australia", 5.2)); pie.setData(data); pie.setTitle("The Continents: Land Area"); return pie; } }
Uitvoer
Figuur 2: Het voltooide cirkeldiagram van de voorgaande code
De XYChart
De XYChart is een abstracte klasse die de basis vormt van alle grafieken met twee assen in JavaFX. De grafieken met twee assen zijn die waarbij typisch een enkel element een paar vertegenwoordigt en wordt uitgezet in een Cartesisch coördinatengebied dat wordt gemarkeerd door de x-as als kolommen en de y-as als rijen. De concrete afgeleiden van deze abstracte klasse zijn:BarChart , AreaChart , BubbleChart , Lijndiagram , Verspreidingsdiagram , StackedAreaChart , en StackedBarChart . In tegenstelling tot XYChart , het cirkeldiagram legt geen gegevens vast in een x- en y-asformaat. Dit is het belangrijkste verschil tussen een PieChart en een XYChart . De gegevens in een XYChart wordt in een reeks besteld. Maar de manier waarop deze reeks gegevens wordt weergegeven, hangt af van de implementatie of het type van de XYChart daadwerkelijk geïnstantieerd.
Omdat XYChart wordt weergegeven in een x- en y-as formaat, de constructor van XYChart is als volgt.
XYChart(Axis<X> xAxis, Axis<Y> yAxis)
As is een abstracte klasse die Regio . uitbreidt . Er zijn twee concrete subklassen van deze klasse, genaamd CategoryAxis en ValueAxis . De CategoryAxis wordt geïnstantieerd om labels van het diagram in tekenreeksformaat weer te geven, terwijl de ValueAxis geeft de gegevensinvoer weer in Number formaat. Het nummer is ook een abstracte klasse die de basisklasse vormt voor alle numerieke typen in Java, zoals de wrapper-klassen:Double , Geheel getal , Zweven , Lang , Kort , enzovoort.
Voorbeeld van staafdiagram
Een staafdiagram wordt meestal gebruikt om het relatieve verschil tussen de verschillende reeksen van een bepaalde categorie weer te geven. Het volgende voorbeeld illustreert hoe u er een kunt maken in Java.
package org.mano.example; import java.util.*; import javafx.application.Application; import javafx.collections.*; import javafx.scene.Scene; import javafx.scene.chart.*; import javafx.scene.chart.XYChart.Series; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { stage.setTitle("JavaFX Chart Demo"); StackPane pane = new StackPane(); pane.getChildren().add(createBarChart()); stage.setScene(new Scene(pane, 400, 200)); stage.show(); } public ObservableList<XYChart.Series<String, Double>> getDummyChartData() { ObservableList<XYChart.Series<String, Double>> data = FXCollections.observableArrayList(); Series<String, Double> as = new Series<>(); Series<String, Double> bs = new Series<>(); Series<String, Double> cs = new Series<>(); Series<String, Double> ds = new Series<>(); Series<String, Double> es = new Series<>(); Series<String, Double> fs = new Series<>(); as.setName("A-Series"); bs.setName("B-Series"); cs.setName("C-Series"); ds.setName("D-Series"); es.setName("E-Series"); fs.setName("F-Series"); Random r = new Random(); for (int i = 1900; i < 2017; i += 10) { as.getData().add(new XYChart.Data<> (Integer.toString(i), r.nextDouble())); bs.getData().add(new XYChart.Data<> (Integer.toString(i), r.nextDouble())); cs.getData().add(new XYChart.Data<> (Integer.toString(i), r.nextDouble())); ds.getData().add(new XYChart.Data<> (Integer.toString(i), r.nextDouble())); es.getData().add(new XYChart.Data<> (Integer.toString(i), r.nextDouble())); fs.getData().add(new XYChart.Data<> (Integer.toString(i), r.nextDouble())); } data.addAll(as, bs, cs, ds, es, fs); return data; } public XYChart<CategoryAxis, NumberAxis> createBarChart() { CategoryAxis xAxis = new CategoryAxis(); NumberAxis yAxis = new NumberAxis(); BarChart bc = new BarChart<>(xAxis, yAxis); bc.setData(getDummyChartData()); bc.setTitle("Bar Chart on Random Number"); return bc; } }
Uitvoer
Figuur 3: Het voltooide staafdiagram van de voorgaande code
ScatterChart-voorbeeld
De gegevensitems in een spreidingsdiagram worden weergegeven als symbolen binnen het gebied van de XY-as. De vorige streepjesdiagramcode kan eenvoudig worden omgezet in een spreidingsdiagram door de volgende wijzigingen aan te brengen.
package org.mano.example; import java.util.*; import javafx.application.Application; import javafx.collections.*; import javafx.scene.Scene; import javafx.scene.chart.*; import javafx.scene.chart.XYChart.Series; import javafx.scene.layout.StackPane; import javafx.stage.Stage; import javafx.util.StringConverter; public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { stage.setTitle("JavaFX Chart Demo"); StackPane pane = new StackPane(); pane.getChildren().add(createScatterChart()); stage.setScene(new Scene(pane, 400, 200)); stage.show(); } public ObservableList<XYChart.Series<String, Double>> getDummyChartData() { // ... Same as above } public XYChart<CategoryAxis, NumberAxis> createScatterChart() { CategoryAxis xAxis = new CategoryAxis(); NumberAxis yAxis = new NumberAxis(); ScatterChart sc = new ScatterChart<>(xAxis, yAxis); sc.setData(getDummyChartData()); sc.setTitle("Scatter chart on random data"); return sc; } }
Uitvoer
Figuur 4: Het voltooide spreidingsdiagram van de voorgaande code
Lijndiagramvoorbeeld
Zoals we kunnen zien, worden de gegevensitems in het spreidingsdiagram weergegeven met behulp van stippen of symbolen. Soms is het handig om de punten met elkaar te verbinden. Dit verbetert de zichtbaarheid van veranderingen in trends van het ene gemarkeerde punt naar het andere. Het lijndiagram doet precies dit. Het volgende voorbeeld illustreert het idee.
package org.mano.example; // ... Import statements same as above public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { stage.setTitle("JavaFX Chart Demo"); StackPane pane = new StackPane(); pane.getChildren().add(createLineChart()); stage.setScene(new Scene(pane, 400, 200)); stage.show(); } public ObservableList<XYChart.Series<String, Double>> getDummyChartData() { // ... Same as above } public XYChart<CategoryAxis, NumberAxis> createLineChart() { CategoryAxis xAxis = new CategoryAxis(); NumberAxis yAxis = new NumberAxis(); LineChart lc = new LineChart<>(xAxis, yAxis); lc.setData(getDummyChartData()); lc.setTitle("Line chart on random data"); return lc; } }
Uitvoer
Figuur 5: Het voltooide lijndiagram van de voorgaande code
Voorbeeld StackedBarChart
De StackedBarChart is een andere versie van de BarChart in die zin dat hier, in plaats van verschillende balken naast elkaar weer te geven, de StackedBarChart stapelt de categorieën op elkaar.
package org.mano.example; // ... Import statements same as above public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { stage.setTitle("JavaFX Chart Demo"); StackPane pane = new StackPane(); pane.getChildren().add(createStackedBarChart()); stage.setScene(new Scene(pane, 400, 200)); stage.show(); } public ObservableList<XYChart.Series<String, Double>> getDummyChartData() { // ... Same as above } public XYChart<CategoryAxis, NumberAxis> createStackedBarChart() { CategoryAxis xAxis = new CategoryAxis(); NumberAxis yAxis = new NumberAxis(); StackedBarChart sbc = new StackedBarChart<>(xAxis, yAxis); sbc.setData(getDummyChartData()); sbc.setTitle("Stacked bar chart on random data"); return sbc; } }
Uitvoer
Figuur 6: Het voltooide gestapelde staafdiagram van de voorgaande code
AreaChart-voorbeeld
In een AreaChart , het gebied onder de lijnen die de punten verbinden, is gevuld om een categorie weer te geven.
package org.mano.example; // ... Import statements same as above public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { stage.setTitle("JavaFX Chart Demo"); StackPane pane = new StackPane(); pane.getChildren().add(createAreaChart()); stage.setScene(new Scene(pane, 400, 200)); stage.show(); } public ObservableList<XYChart.Series<String, Double>> getDummyChartData() { // ... Same as above } public XYChart<CategoryAxis, NumberAxis> createAreaChart() { CategoryAxis xAxis = new CategoryAxis(); NumberAxis yAxis = new NumberAxis(); AreaChart ac = new AreaChart<>(xAxis, yAxis); ac.setData(getDummyChartData()); ac.setTitle("Area chart on random data"); return ac; } }
Uitvoer
Figuur 7: Het voltooide vlakdiagram van de voorgaande code
Voorbeeld StackedAreaChart
De StackedAreaChart toont de som van de waarden van dezelfde categorie en toont geen afzonderlijke gebieden zoals de AreaChart doet. Dit is in wezen een andere versie van de AreaChart .
package org.mano.example; // ... Import statements same as above public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { stage.setTitle("JavaFX Chart Demo"); StackPane pane = new StackPane(); pane.getChildren().add(createStackedAreaChart()); stage.setScene(new Scene(pane, 400, 200)); stage.show(); } public ObservableList<XYChart.Series<String, Double>> getDummyChartData() { // ... Same as above } public XYChart<CategoryAxis, NumberAxis> createStackedAreaChart() { CategoryAxis xAxis = new CategoryAxis(); NumberAxis yAxis = new NumberAxis(); StackedAreaChart sac = new StackedAreaChart<>(xAxis, yAxis); sac.setData(getDummyChartData()); sac.setTitle("Stacked area chart on random data"); return sac; } }
Uitvoer
Figuur 8: Het voltooide gestapelde vlakdiagram van de voorgaande code
BubbleChart-voorbeeld
De BubbleChart plot bubbels voor gegevenspunten in de reeks. Deze variant van de XYChart maakt gebruik van de aanvullende eigenschappen van de XYChart.Data klasse in die zin dat het een speciale XYChart . is implementatie onder alle subklassen van de XYChart . Hier wordt een gegevensitem aangeduid met twee of drie parameters, zoals x-waarde, y-waarde en, optioneel, de waarde die de straal van de bel aangeeft. Hier is een voorbeeld om te illustreren hoe u er een kunt maken in Java.
package org.mano.example; import java.util.*; import javafx.application.Application; import javafx.collections.*; import javafx.scene.Scene; import javafx.scene.chart.*; import javafx.scene.chart.XYChart.Series; import javafx.scene.layout.StackPane; import javafx.stage.Stage; import javafx.util.StringConverter; public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) throws Exception { stage.setTitle("JavaFX Chart Demo"); StackPane pane = new StackPane(); pane.getChildren().add(createBubbleChart()); stage.setScene(new Scene(pane, 400, 200)); stage.show(); } public ObservableList<XYChart.Series<Integer, Double>> getDummyChartData2() { ObservableList<XYChart.Series<Integer, Double>> data = FXCollections.observableArrayList(); Series<Integer, Double> as = new Series<>(); Series<Integer, Double> bs = new Series<>(); Series<Integer, Double> cs = new Series<>(); Series<Integer, Double> ds = new Series<>(); Series<Integer, Double> es = new Series<>(); Series<Integer, Double> fs = new Series<>(); as.setName("A-Series"); bs.setName("B-Series"); cs.setName("C-Series"); ds.setName("D-Series"); es.setName("E-Series"); fs.setName("F-Series"); Random r = new Random(); for (int i = 1900; i < 2017; i += 10) { double d = r.nextDouble(); as.getData().add(new XYChart.Data<> (i, r.nextInt(32)+r.nextDouble(), 2 * d)); bs.getData().add(new XYChart.Data<> (i,r.nextInt(32)+r.nextDouble(), 4 * d)); cs.getData().add(new XYChart.Data<> (i,r.nextInt(32)+r.nextDouble(), 3 * d)); ds.getData().add(new XYChart.Data<> (i,r.nextInt(32)+r.nextDouble(), 5 * d)); es.getData().add(new XYChart.Data<> (i,r.nextInt(32)+r.nextDouble(), 1.5 * d)); fs.getData().add(new XYChart.Data<> (i,r.nextInt(32)+r.nextDouble(), 1.7 * d)); } data.addAll(as, bs, cs, ds, es, fs); return data; } public BubbleChart<Number, Number> createBubbleChart() { NumberAxis xAxis = new NumberAxis(); NumberAxis yAxis = new NumberAxis(); yAxis.setAutoRanging(false); yAxis.setLowerBound(0); yAxis.setUpperBound(30); xAxis.setAutoRanging(false); xAxis.setLowerBound(1900); xAxis.setUpperBound(2017); xAxis.setTickUnit(10); xAxis.setTickLabelFormatter(new StringConverter<Number>() { @Override public String toString(Number object) { return String.valueOf(object.intValue() / 10); } @Override public Number fromString(String string) { return Integer.valueOf(string) * 10; } }); BubbleChart blc = new BubbleChart<>(xAxis, yAxis); blc.setData(getDummyChartData2()); blc.setTitle("Bubble chart on random data"); return blc; } }
Uitvoer
Figuur 9: Het voltooide bellendiagram uit de voorgaande code
Conclusie
Men kan Cascading Style Sheets (CSS) gebruiken om het standaard uiterlijk van de JavaFX-diagrammen te wijzigen, zoals het wijzigen van het kleurenschema, het wijzigen van hun legenda's en assen of diagramsymbolen, enzovoort. JavaFX biedt veel diagramspecifieke CSS-tags om dit te bereiken. Het belangrijkste onderdeel van de JavaFX-grafiek-API is dat deze verschillende variaties van kant-en-klare grafiektypen biedt. Het is aan de ontwikkelaars om het juiste type diagram te kiezen dat het beste past bij hun gegevensrapportageschema.