如何知道何时显示图表数据?

时间:2014-05-20 18:50:17

标签: charts javafx

我正在为LineChart中的JavaFX添加一些功能,我主要使用图表Axis中的这些方法:

  • 轴#getDisplayPosition
  • 轴#getValueForDisplay

问题是这种方法只在我添加到图表中的新数据被渲染时才返回正确的值。所以现在我有这个丑陋的解决方法:

 new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        // Axis#getDisplayPosition and Axis#getValueForDisplay usage
                    }
                });
            }
        }, 10);

一个计时器,至少在我的电脑中延迟执行代码10mS,以便在屏幕上呈现新数据,这样我就可以使用这种方法了。有没有其他方法可以知道图表何时呈现?我一直在寻找我可以从LineChart覆盖的所有方法,但我找不到一个可以帮助我知道图表何时完成渲染的方法。

这是一个简单的代码来重现我的意思:

    import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

import java.util.Random;

public class Main extends Application {

    @Override
    public void start(final Stage primaryStage) throws Exception{

        final LineChart lineChart = new LineChart(new NumberAxis(), new NumberAxis());
        final XYChart.Series<Integer, Integer> series = new XYChart.Series<Integer, Integer>();
        ObservableList<XYChart.Series<Integer, Integer>> seriesDataSet = FXCollections.observableArrayList();

        lineChart.setAnimated(false);
        lineChart.setPrefWidth(800);
        lineChart.setPrefHeight(600);
        seriesDataSet.add(series);
        lineChart.setData(seriesDataSet);

        for (int n = 0; n < 50; ++n) {
            series.getData().add(new XYChart.Data<Integer, Integer>(n, new Random().nextInt(20)));
        }

        Pane pane = new Pane();
        pane.getChildren().add(lineChart);

        primaryStage.setScene(new Scene(pane, 800, 600));
        primaryStage.show();

        // Get a display
        System.out.println(lineChart.getXAxis().getDisplayPosition(2));
        // The value is now correct and different from the previous one
        System.out.println(lineChart.getXAxis().getDisplayPosition(2));

        // Add data to the chart
        for (int n = 51; n < 80; ++n) {
            series.getData().add(new XYChart.Data<Integer, Integer>(n, new Random().nextInt(20)));
        }

        // Get a display
        System.out.println(lineChart.getXAxis().getDisplayPosition(2));
        // The value is now correct and different from the previous one
        System.out.println(lineChart.getXAxis().getDisplayPosition(2));

        pane.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                System.out.println(lineChart.getXAxis().getDisplayPosition(2));
            }
        });
    }


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

打印的前两个数字是相同的,然后我添加一些数据,数字仍然是相同的错误,它们应该与以前的数字不同,因为我添加了数据。现在单击图表中的某个位置,您将读取正确的数字,因为图表已经呈现。

2 个答案:

答案 0 :(得分:1)

这方面的诀窍是图表上的三倍:

  1. 在修改数据之前关闭animation
  2. applyCSS
  3. 请求layout
  4. 然后,JavaFX系统将被迫计算图表组件的所有位置。之后,您可以查询组件以确定其当前布局位置和边界。

    确保实际渲染的方法是将图表放在临时场景中并snapshot。但是,除非您确实需要将渲染图像用于其他目的,否则applyCSS / layout组合通常是您进行位置计算所需的全部内容。

答案 1 :(得分:0)

如果我只是移动stage.show,它在java 8中工作正常。已更新以添加更多数据。

// Add data to the chart
    for (int n = 0; n < 50; ++n) {
        series.getData().add(new XYChart.Data<Integer, Integer>(n, new Random().nextInt(20)));
    }

    Pane pane = new Pane();
    pane.getChildren().add(lineChart);

    primaryStage.setScene(new Scene(pane, 800, 600));
    primaryStage.show();

    // Get a display
    System.out.println(lineChart.getXAxis().getDisplayPosition(2));
    // The value is now correct and different from the previous one
    System.out.println(lineChart.getXAxis().getDisplayPosition(2));

    // Add data to the chart
    for (int n = 51; n < 80; ++n) {
        series.getData().add(new XYChart.Data<Integer, Integer>(n, new Random().nextInt(20)));
    }

    // Get a display
    System.out.println(lineChart.getXAxis().getDisplayPosition(5));
    // The value is now correct and different from the previous one
    System.out.println(lineChart.getXAxis().getDisplayPosition(5));
当你按照它的方式运行时,

sout显示30,30而不是0 30。 现在它在添加更多数据后显示30​​,30,74,74。

我刚刚删除了任务和runlater。我认为这会弄乱GUI线程。由于必须在GUI线程上添加到图表,我猜它会等到返回并询问该位置。

顺便说一句,如果我打开动画,我仍然可以得到合适的数量。有趣的是,在动画完成之前,金额会正确打印。