2013-03-25 8 views
7

Sto provando a creare un grafico a serie utilizzando JavaFX, in cui i dati vengono inseriti dinamicamente.Come aggiungere un indicatore di valore alla tabella JavaFX?

Ogni volta che viene inserito un nuovo valore, vorrei verificare se questo è il valore più alto finora, e in tal caso, voglio disegnare una linea orizzontale per mostrare che questo è il valore massimo.

Nella JFree chart avrei usato un ValueMarker, ma sto cercando di fare lo stesso con JavaFX.

Ho provato a utilizzare l'oggetto Linea, ma non è sicuramente lo stesso, perché non posso fornire i valori del grafico, esso prende le posizioni relative dei pixel nelle finestre.

Ecco lo screenshot del grafico che voglio raggiungere:

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

Qualche suggerimento? Grazie.

risposta

14

Per convertire i valori del grafico in pixel è possibile utilizzare il metodo NumberAxis#getDisplayPosition() che restituisce le coordinate effettive dei nodi del grafico.

Anche se queste coordinate sono relative al grafico ad area, che si può scoprire dal codice successivo:

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

Nota localToScene() metodo che permette di convertire qualsiasi coordinate a quelle di scena. Quindi puoi usarli per aggiornare le coordinate del tuo indicatore di valore. Assicurati di effettuare la chiamata localToScene dopo che la scena è stata mostrata.

programma di esempio vedere di seguito, che produce tabella:

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 bel dirtyness :-) – kleopatra

+0

btw, ha cambiato il codice un po 'per far fronte con i genitori ridimensionabili http: // StackOverflow. it/a/24403761/203657 – kleopatra

+0

@kleopatra, grazie! Ma perché la sporcizia? :) –

Problemi correlati