9

データが動的に挿入されるJavaFXを使用して系列グラフを作成しようとしています。

新しい値を挿入するたびに、これがこれまでの最高値であるかどうかを確認したいと思います。その場合は、これが最大値であることを示すために水平線を描画します。

JFreeチャートではValueMarkerを使用していましたが、JavaFXでも同じことをしようとしています。

Lineオブジェクトを使用してみましたが、Chart値を提供できないため、ウィンドウ内の相対的なピクセル位置を取得するため、まったく同じではありません。

これが私が達成したいチャートのスクリーンショットです:

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

助言がありますか?ありがとうございました。

4

1 に答える 1

15

チャート値をピクセルに変換するNumberAxis#getDisplayPosition()には、チャートノードの実際の座標を返すメソッドを使用できます。

これらの座標はチャート領域を基準にしていますが、次のコードで確認できます。

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

localToScene()任意の座標をシーンの座標に変換できるメソッドに注意してください。したがって、それらを使用して値マーカーの座標を更新できます。localToSceneシーンが表示されたら、必ず電話をかけてください。

次のチャートを作成する以下のサンプルプログラムを参照してください。

ここに画像の説明を入力してください

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();
    }
}
于 2013-03-28T13:55:31.320 に答える