2017-05-25 3 views
1

Je crée un graphique à barres basé sur l'entrée de l'utilisateur fournie par une boîte de choix. Dans l'écouteur de changement de boîte de choix, je crée d'abord une série de données, puis le graphique à barres. Cependant, le graphique ne s'affiche pas correctement, c'est-à-dire qu'il n'y a pas de barres pendant un certain temps, la durée des barres n'est pas la même que celle des données. Mais, lorsque j'ajoute un court délai entre la création des données et la création du graphique en mettant le thread de l'interface utilisateur en veille, cela fonctionne très bien.Pourquoi le thread de l'interface utilisateur javafx8 se comporte étrangement à l'intérieur d'un listeur de changement?

Ma question est: pourquoi cela se passe-t-il? Pourquoi le thread d'interface utilisateur n'attend pas la fin du processus de création de données avant de créer le graphique? Est-il possible de le faire sans ajouter de délai? Voici l'extrait de code de l'écouteur de modification.

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

Le code complet est comme suit:

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

Répondre

2

qui ressemble à un bug ... (dans l'API graphique, je ne suis pas entièrement surpris).

Cela semble fonctionner correctement si vous désactivez l'animation. Appelez

barChart.setAnimated(false); 

immédiatement après la création du diagramme à barres.

+0

Merci James_D, tu as fait ma journée. J'ai passé les deux derniers jours à comprendre pourquoi ça ne marche pas. Très appréciée. – Adnan