2013-03-25 2 views
7

Ich versuche, ein Seriendiagramm mit JavaFX zu erstellen, wo Daten dynamisch eingefügt werden.Wie füge ich einen Wertmarker zum JavaFX-Diagramm hinzu?

Jedes Mal, wenn ein neuer Wert eingefügt wird, möchte ich prüfen, ob dies der höchste Wert ist, und wenn ja, möchte ich eine horizontale Linie zeichnen, um zu zeigen, dass dies der maximale Wert ist.

In JFree-Diagramm hätte ich einen ValueMarker verwendet, aber ich versuche, das gleiche mit JavaFX zu tun.

Ich habe versucht, mit der Linie Objekt, aber es ist definitiv nicht das Gleiche, weil ich die Diagrammwerte nicht bereitstellen kann, nimmt es die relativen Pixelpositionen in den Fenstern. Hier

ist der Screenshot des Diagramms ich erreichen möchte:

http://postimg.org/image/s5fkupsuz/

Irgendwelche Vorschläge? Danke.

Antwort

14

Um Diagrammwerte in Pixel zu konvertieren, können Sie die Methode NumberAxis#getDisplayPosition() verwenden, die die tatsächlichen Koordinaten der Diagrammknoten zurückgibt.

Obwohl diese Koordinaten sind relativ Bereich Grafik, die Sie mit dem nächsten Code herausfinden können:

Node chartArea = chart.lookup(".chart-plot-background"); 
Bounds chartAreaBounds = chartArea.localToScene(chartArea.getBoundsInLocal()); 

Hinweis localToScene() Methode, die Sie Szene diejenigen, alle Koordinaten zu konvertieren. Sie können damit Ihre Wertmarkenkoordinaten aktualisieren. Stellen Sie sicher, dass Sie localToScene anrufen, nachdem Ihre Szene angezeigt wurde.

Siehe Beispielprogramm, unter der erzeugt folgenden Tabelle: // Stackoverflow:

enter image description here

public class LineChartValueMarker extends Application { 

    private Line valueMarker = new Line(); 
    private XYChart.Series<Number, Number> series = new XYChart.Series<>(); 
    private NumberAxis yAxis; 
    private double yShift; 

    private void updateMarker() { 
     // find maximal y value 
     double max = 0; 
     for (Data<Number, Number> value : series.getData()) { 
      double y = value.getYValue().doubleValue(); 
      if (y > max) { 
       max = y; 
      } 
     } 
     // find pixel position of that value 
     double displayPosition = yAxis.getDisplayPosition(max); 
     // update marker 
     valueMarker.setStartY(yShift + displayPosition); 
     valueMarker.setEndY(yShift + displayPosition); 
    } 

    @Override 
    public void start(Stage stage) { 
     LineChart<Number, Number> chart = new LineChart<>(new NumberAxis(0, 100, 10), yAxis = new NumberAxis(0, 100, 10)); 

     series.getData().add(new XYChart.Data(0, 0)); 
     series.getData().add(new XYChart.Data(10, 20)); 

     chart.getData().addAll(series); 
     Pane pane = new Pane(); 
     pane.getChildren().addAll(chart, valueMarker); 
     Scene scene = new Scene(pane); 

     // add new value on mouseclick for testing 
     chart.setOnMouseClicked(new EventHandler<MouseEvent>() { 
      @Override 
      public void handle(MouseEvent t) { 
       series.getData().add(new XYChart.Data(series.getData().size() * 10, 30 + 50 * new Random().nextDouble())); 
       updateMarker(); 
      } 
     }); 

     stage.setScene(scene); 
     stage.show(); 

     // find chart area Node 
     Node chartArea = chart.lookup(".chart-plot-background"); 
     Bounds chartAreaBounds = chartArea.localToScene(chartArea.getBoundsInLocal()); 
     // remember scene position of chart area 
     yShift = chartAreaBounds.getMinY(); 
     // set x parameters of the valueMarker to chart area bounds 
     valueMarker.setStartX(chartAreaBounds.getMinX()); 
     valueMarker.setEndX(chartAreaBounds.getMaxX()); 
     updateMarker(); 
    } 

    public static void main(String[] args) { 
     launch(); 
    } 
} 
+0

+1 schön geekelt :-) – kleopatra

+0

btw, Ihren Code ein wenig mit der Größe veränderbar Eltern http fertig zu werden geändert. com/a/24403761/203657 – kleopatra

+0

@kleopatra, danke! Aber warum Schmutzigkeit? :) –