Database
 sql >> Datenbank >  >> RDS >> Database

Arbeiten mit JavaFX Chart APIs

Einer der wichtigsten Aspekte der Berichterstattung ist es, den Inhalt so gut wie möglich sichtbar zu machen, damit die Essenz der im Bericht enthaltenen Informationen schnell und mühelos sein Publikum erreicht. Diagramme spielen dabei eine entscheidende Rolle. Die Präsentation von Rohdaten und der Versuch, sich das mit den Daten verbundene Szenario vorzustellen, ist nicht sehr einfach, aber Diagramme stellen eine bildliche Essenz der Daten dar und helfen dem Betrachter, die Idee hinter den Rohdaten sehr schnell zu erfassen. JavaFX verfügt über eine integrierte Unterstützung, um grobe Daten dynamisch in malerischer Form darzustellen. Die API hat zwei Facetten:Man kann entweder die API-Klassen erweitern und ein benutzerdefiniertes Diagramm von Grund auf neu erstellen oder die verfügbaren diagrammspezifischen Klassen verwenden, um ein Diagramm mit sehr wenig Code zu erstellen. Dieser Artikel befasst sich mit den wichtigsten Aspekten der Chart-APIs von JavaFX und zeigt, wie man sie implementiert. Es werden schnelle Beispiele bereitgestellt, um Ihnen zu helfen.

JavaFX-Diagramme

JavaFX-Diagramme lassen sich nicht nur einfach in andere Teile der Anwendung integrieren, sondern werden auch von der erweiterbaren Richtlinie der objektorientierten Technologie durchdrungen, die je nach Bedarf des Entwicklers angepasst werden kann. Das ist nichts Neues, denn objektorientierte Designs sollen immer erweiterbar sein, aber der interessante Teil der JavaFX-Chart-API ist, dass es viele vorgefertigte Chart-Klassen gibt, die mit einer kleinen oder keiner Änderung instanziiert werden können Eigenschaften, um professionell aussehende Diagramme zu erhalten. Diese Diagrammklassen sind am gebräuchlichsten, anpassbar und erfüllen fast alle Anforderungen des Entwicklers. In den meisten Fällen ist es kaum erforderlich, ein benutzerdefiniertes Diagramm von Grund auf neu zu erstellen.

JavaFX bietet acht solcher Diagrammtypen in der API-Bibliothek mit ihrer integrierten Funktionalität. Obwohl es viele unterstützende Klassen und Schnittstellen in der JavaFX-Chart-API-Bibliothek gibt, ist die konkrete achte Implementierung wie folgt hierarchisch angeordnet.


Abbildung 1: Das Hierarchiediagramm der JavaFX-Diagramm-API-Bibliothek

Daher sind die acht gängigen Diagrammtypen:Kreisdiagramm , Balkendiagramm , Flächendiagramm , Liniendiagramm , Streudiagramm , Blasendiagramm , gestapeltes Flächendiagramm und gestapeltes Balkendiagramm .

Das Tortendiagramm

Das Kreisdiagramm ist ein gängiges Diagrammformat, bei dem Informationen in einer typischen Kreissegmentstruktur gerendert werden. Jedes Tortenstück repräsentiert den proportionalen Wert der Daten. Der einfachste Weg, ein Tortendiagramm in JavaFX zu erstellen, besteht darin, das PieChart zu instanziieren class und setzen Sie die Daten wie folgt:

PieChart pie=new PieChart();

Wir können die Daten für ein Tortendiagramm mit Hilfe von setData() setzen -Methode, die einen Parameter vom Typ ObservableList akzeptiert . Die Instanz von PieChart.Data ist eigentlich eine verschachtelte Klasse von PieChart und rendert ein Stück der Tortendaten. Der Konstruktor akzeptiert zwei Parameter, wie folgt:

PieChart.Data(String title, Double value)

Hier ist ein kurzes Beispiel zum Erstellen eines Tortendiagramms.

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;
   }
}

Ausgabe


Abbildung 2: Das fertige Tortendiagramm aus dem vorherigen Code

Das XY-Diagramm

Das XYChart ist eine abstrakte Klasse, die die Grundlage aller zweiachsigen Diagramme in JavaFX bildet. Die zweiachsigen Diagramme sind solche, bei denen typischerweise ein einzelnes Element ein Paar darstellt und in einem kartesischen Koordinatenbereich gezeichnet wird, der durch die x-Achse als Spalten und die y-Achse als Zeilen gekennzeichnet ist. Die konkreten Ableitungen dieser abstrakten Klasse sind:BarChart , AreaChart , BubbleChart , Liniendiagramm , ScatterChart , StackedAreaChart und StackedBarChart . Im Gegensatz zu XYChart , das Kreisdiagramm legt keine Daten in einem x- und y-Achsenformat fest. Dies ist der Hauptunterschied zwischen einem PieChart und ein XYChart . Die Daten in einem XYChart wird in Serie bestellt. Die Art und Weise, wie diese Datenreihe gerendert wird, hängt jedoch von der Implementierung oder dem Typ des XYChart ab tatsächlich instanziiert.

Weil XYChart wird in einem x- und y-Achsenformat dargestellt, dem Konstruktor von XYChart ist wie folgt.

XYChart(Axis<X> xAxis, Axis<Y> yAxis)

Achse ist eine abstrakte Klasse, die Region erweitert . Es gibt zwei konkrete Unterklassen dieser Klasse, genannt CategoryAxis und ValueAxis . Die Kategorieachse wird instanziiert, um Beschriftungen des Diagramms im Zeichenfolgenformat zu rendern, während die ValueAxis gibt die Dateneinträge in Number wieder Format. Die Nummer ist auch eine abstrakte Klasse, die die Basisklasse für alle numerischen Typen in Java bildet, wie zum Beispiel die Wrapper-Klassen:Double , Ganzzahl , Schweben , Lang , Kurz , und so weiter.

Balkendiagramm-Beispiel

Ein Balkendiagramm wird normalerweise verwendet, um den relativen Unterschied zwischen den verschiedenen Serien einer bestimmten Kategorie anzuzeigen. Das folgende Beispiel veranschaulicht, wie man eine in Java erstellt.

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;
   }
}

Ausgabe


Abbildung 3: Das fertige Balkendiagramm aus dem vorangegangenen Code

ScatterChart-Beispiel

Die Datenelemente in einem Punktdiagramm werden als Symbole im Bereich der XY-Achse dargestellt. Der vorherige Balkendiagramm-Code kann leicht konvertiert werden, um ein Streudiagramm zu erstellen, indem Sie die folgenden Änderungen vornehmen.

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;
   }
}

Ausgabe


Abbildung 4: Das fertige Streudiagramm aus dem vorherigen Code

Liniendiagramm-Beispiel

Wie wir sehen können, werden die Datenelemente im Punktdiagramm mit Hilfe von Punkten oder Symbolen dargestellt. Manchmal ist es praktisch, die Punkte zu verbinden. Dies verbessert die Sichtbarkeit von Trendänderungen von einem markierten Punkt zum anderen. Das Liniendiagramm tut genau dies. Das nächste Beispiel veranschaulicht die 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;
   }
}

Ausgabe


Abbildung 5: Das fertige Liniendiagramm aus dem vorherigen Code

StackedBarChart-Beispiel

Das StackedBarChart ist eine andere Version des Balkendiagramms in dem Sinne, dass hier, anstatt verschiedene Balken nebeneinander darzustellen, das StackedBarChart stapelt die Kategorien übereinander.

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;
   }
}

Ausgabe


Abbildung 6: Das fertige gestapelte Balkendiagramm aus dem vorherigen Code

AreaChart-Beispiel

In einem AreaChart , wird der Bereich unter den Linien, die die Punkte verbinden, ausgefüllt, um eine Kategorie darzustellen.

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;

   }
}

Ausgabe


Abbildung 7: Das fertige Flächendiagramm aus dem vorhergehenden Code

StackedAreaChart-Beispiel

Das StackedAreaChart zeigt die Summe der Werte derselben Kategorie und zeigt nicht einzelne Bereiche wie das AreaChart tut. Dies ist im Wesentlichen eine andere Version des 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;
   }
}

Ausgabe


Abbildung 8: Das fertige gestapelte Flächendiagramm aus dem vorherigen Code

BubbleChart-Beispiel

Das BubbleChart zeichnet Blasen für Datenpunkte in der Reihe. Diese Variante des XYChart nutzt die zusätzlichen Eigenschaften von XYChart.Data Klasse in dem Sinne, dass es sich um ein spezielles XYChart handelt Implementierung unter allen Unterklassen des XYChart . Hier wird ein Datenelement durch zwei oder drei Parameter bezeichnet, wie z. B. x-Wert, y-Wert und optional den Wert, der den Radius der Blase angibt. Hier ist ein Beispiel, um zu veranschaulichen, wie man eine in Java erstellt.

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;
   }
}

Ausgabe


Abbildung 9: Das fertige Blasendiagramm aus dem vorherigen Code

Schlussfolgerung

Man kann Cascading Style Sheets (CSS) verwenden, um das standardmäßige Erscheinungsbild der JavaFX-Diagramme zu ändern, z. B. das Farbschema zu ändern, ihre Legenden und Achsen oder Diagrammsymbole zu ändern und so weiter. JavaFX bietet viele diagrammspezifische CSS-Tags, um dies zu erreichen. Der wichtigste Teil der JavaFX-Diagramm-API ist, dass sie verschiedene Variationen von gebrauchsfertigen Diagrammtypen bereitstellt. Es liegt an den Entwicklern, den richtigen Diagrammtyp auszuwählen, der am besten zu ihrem Datenberichtsschema passt.