为什么javafx8 UI线程在更改列表器中表现奇怪?

时间:2017-05-25 19:37:10

标签: java multithreading javafx javafx-8

我正在根据通过选择框提供的用户输入创建条形图。在选择框更改侦听器内部,我首先创建一个数据系列,然后创建条形图。但是,图表没有正确渲染,即有些时候没有条形图,有时条形图的长度与数据不同。但是,当我通过将UI线程置于睡眠状态而在数据创建和图表创建之间添加一个短暂的延迟时,它可以正常工作。

我的问题是,为什么会这样?为什么UI线程在创建图表之前没有等待数据创建过程完成?有没有办法在不增加延迟的情况下做到这一点?下面是更改侦听器的代码片段。

numberOfBars.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
   createData(newValue);
   // It works fine if I add Thread.sleep(1000) here. Why?
   createBarChart();
});

完整的代码如下:

public class Main extends Application {
    private XYChart.Series<String, Number> data = new XYChart.Series<>();
    private VBox vBox = new VBox();
    private Pane bcContainer = new Pane();
    @Override public void start(Stage stage){
        ChoiceBox<Integer> numberOfBars = new ChoiceBox<>();
        ObservableList<Integer> items = FXCollections.observableArrayList(5, 10);
        numberOfBars.setItems(items);
        vBox.getChildren().addAll(new Label("Number of bars: "), numberOfBars, new Separator(), bcContainer);
        numberOfBars.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            createData(newValue);
            // It works fine if I add Thread.sleep(1000) here. Why?
            createBarChart();
        });
        Scene scene  = new Scene(vBox,800,600);
        stage.setScene(scene);
        stage.show();
    }
    private void createData(int bars){
        ObservableList<XYChart.Data<String, Number>> observableList = FXCollections.observableArrayList();
        for (int i=0; i<bars; i++) {
            observableList.add(new XYChart.Data<>("bar" + Integer.toString(i), i+1));
        }
        data.setData(observableList);
    }
    private void createBarChart(){
        BarChart<String, Number> barChart= new BarChart<>(new CategoryAxis(), new NumberAxis());
        barChart.setLegendVisible(false);
        barChart.setPrefSize(800, 500);
        barChart.getData().add(data);
        bcContainer.getChildren().clear();
        bcContainer.getChildren().add(barChart);
    }
    public static void main(String[] args) {
        launch(args);
    }
}

1 个答案:

答案 0 :(得分:2)

这看起来像个错误......(在图表API中,我并不完全惊讶)。

如果关闭动画,它似乎工作正常。呼叫

barChart.setAnimated(false);
创建条形图后立即