如何向 JavaFX 图表添加值标记? [英] How to add a value marker to JavaFX chart?

查看:38
本文介绍了如何向 JavaFX 图表添加值标记?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 JavaFX 构建一个系列图表,其中数据是动态插入的.

每次插入一个新值时,我想检查这是否是迄今为止的最高值,如果是,我想画一条水平线来显示这是最大值.

在 JFree 图表中,我会使用 ValueMarker,但我试图用 JavaFX 做同样的事情.

我尝试使用 Line 对象,但它绝对不一样,因为我无法提供 Chart 值,它需要窗口中的相对像素位置.

这是我想要实现的图表截图:

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

有什么建议吗?谢谢.

解决方案

要将图表值转换为像素,您可以使用方法 NumberAxis#getDisplayPosition() 返回图表节点的实际坐标.>

虽然这些坐标是相对于图表区域的,您可以通过下一个代码找到:

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

注意 localToScene() 方法,它允许您将任何坐标转换为场景坐标.因此,您可以使用它们来更新您的值标记坐标.确保在显示场景后调用 localToScene.

请参阅下面的示例程序,该程序生成下一个图表:

public class LineChartValueMarker extends Application {私人线值标记 = 新线();私人 XYChart.Series<数字,数字>系列 = 新的 XYChart.Series<>();私有 NumberAxis yAxis;私人双yShift;私有无效更新标记(){//找到最大的 y 值双最大 = 0;for (Data value : series.getData()) {double y = value.getYValue().doubleValue();如果 (y > 最大值) {最大值 = y;}}//找到该值的像素位置double displayPosition = yAxis.getDisplayPosition(max);//更新标记valueMarker.setStartY(yShift + displayPosition);valueMarker.setEndY(yShift + displayPosition);}@覆盖公共无效开始(阶段阶段){LineChart<数字,数字>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);窗格窗格 = new Pane();pane.getChildren().addAll(chart, valueMarker);场景场景 = 新场景(窗格);//在鼠标单击时添加新值以进行测试chart.setOnMouseClicked(new EventHandler() {@覆盖公共无效句柄(鼠标事件 t){series.getData().add(new XYChart.Data(series.getData().size() * 10, 30 + 50 * new Random().nextDouble()));更新标记();}});stage.setScene(场景);舞台表演();//找到图表区域节点节点 chartArea = chart.lookup(".chart-plot-background");边界 chartAreaBounds = chartArea.localToScene(chartArea.getBoundsInLocal());//记住图表区域的场景位置yShift = chartAreaBounds.getMinY();//将 valueMarker 的 x 参数设置为图表区域边界valueMarker.setStartX(chartAreaBounds.getMinX());valueMarker.setEndX(chartAreaBounds.getMaxX());更新标记();}公共静态无效主(字符串 [] args){发射();}}

I am trying to build a series chart using JavaFX, where data is inserted dynamically.

Each time that a new value is inserted I would like to check if this is the highest value so far, and if so, I want to draw an horizontal line to show that this is the maximum value.

In JFree chart I would have used a ValueMarker, but I am trying to do the same with JavaFX.

I tried using the Line object, but it is definitely not the same, because I cannot provide the Chart values, it takes the relative pixel positions in the windows.

Here is the screenshot of chart I want to achieve:

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

Any suggestions? Thank you.

解决方案

To convert chart values to pixels you can use method NumberAxis#getDisplayPosition() which return actual coordinates of the chart nodes.

Although these coordinates are relative to chart area, which you can find out by next code:

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

Note localToScene() method which allows you to convert any coordinates to Scene ones. Thus you can use them to update your value marker coordinates. Make sure you make localToScene call after your Scene have been shown.

See sample program below which produces next chart:

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

这篇关于如何向 JavaFX 图表添加值标记?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆