2017-05-25 1 views
0

Bonjour, j'ai un problème avec certains Combo Box. J'ai une interface avec quatre listes déroulantes et ils utilisent comme éléments la même liste. J'ai ajouté un écouteur à l'une de ces listes déroulantes et je voulais que l'auditeur soit fait juste quand je sélectionne un élément et pas quand la liste est changée, mais avec cet écouteur il se lance automatiquement quand j'enlève un élément de la listeréglage de l'écouteur Combobox JavaFX

  class1.getSelectionModel().selectedItemProperty().addListener((options, oldValue, newValue) ->{ 

      System.out.println(oldValue); 
      System.out.println(newValue); 

      class1.getItems().add(oldValue); 
      class1.getItems().remove(newValue); 

      }); 

donc à la fin il exécute cet écouteur chaque fois que je fais la supprimer, et il se termine par une erreur éventuellement

+0

Si vous supprimez l'élément sélectionné, il est clair que la sélection devra changer. Que veux-tu réellement arriver ici? (Pourquoi changez-vous la liste sur un changement dans la sélection?) –

+0

Je voudrais montrer sur la valeur de comboBox l'article que j'ai choisi mais je voulais que cet article soit enlevé de la liste, ainsi quand je cliquerai encore ce combo boîte il affichera comme options tout sauf celui qui est déjà sélectionné –

Répondre

0

le problème se pose essentiellement parce que vous finissez par la modification d'une liste observable (de selectedItems le modèle de sélection) en un changement dans cette liste est en cours de traitement. C'est un défaut de l'API, imo. Une solution de contournement (bidouille) est d'utiliser une liste filtrée, et mettre à jour le prédicat sur la liste dans un Platform.runLater(...), de manière à laisser le premier changement complet avant de le changer à nouveau:

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.collections.transformation.FilteredList; 
import javafx.scene.Scene; 
import javafx.scene.control.ComboBox; 
import javafx.scene.layout.BorderPane; 
import javafx.stage.Stage; 

public class ComboBoxNoSelectedItem extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     ObservableList<String> allItems = FXCollections.observableArrayList("One", "Two", "Three", "Four", "Five"); 
     ComboBox<String> combo = new ComboBox<>(); 
     combo.setValue(allItems.get(0)); 
     FilteredList<String> items = allItems.filtered(item -> item != combo.getValue()); 
     combo.setItems(items); 

     combo.valueProperty().addListener((obs, oldValue, newValue) -> Platform.runLater(() -> items.setPredicate(item -> item != newValue))); 


     BorderPane root = new BorderPane(); 
     root.setTop(combo); 
     primaryStage.setScene(new Scene(root, 400, 400)); 
     primaryStage.show(); 
    } 

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

Peut-être une approche plus propre est juste désactiver la cellule affiche l'élément sélectionné, qui est proche, mais pas tout à fait la même chose, UX:

import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.scene.Scene; 
import javafx.scene.control.ComboBox; 
import javafx.scene.control.ListCell; 
import javafx.scene.layout.BorderPane; 
import javafx.stage.Stage; 

public class ComboBoxNoSelectedItem extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     ObservableList<String> allItems = FXCollections.observableArrayList("One", "Two", "Three", "Four", "Five"); 
     ComboBox<String> combo = new ComboBox<>(allItems); 

     combo.setCellFactory(lv -> new ListCell<String>() { 

      { 
       disableProperty().bind(combo.valueProperty().isEqualTo(itemProperty())); 
      } 

      @Override 
      protected void updateItem(String item, boolean empty) { 
       super.updateItem(item, empty); 
       setText(item); 
      } 
     }); 

     BorderPane root = new BorderPane(); 
     root.setTop(combo); 
     primaryStage.setScene(new Scene(root, 400, 400)); 
     primaryStage.show(); 
    } 

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

ok cela fonctionne mais pour certaines raisons sur les deux ou trois premiers changements supprime même d'autres éléments .. après un certain temps, il fonctionne parfaitement mais je finis par perdre deux ou trois éléments de la liste –

+0

FilteredList items = classi.filtered (item -> item! = class1.getValue()); class1.setItems (items); class1.valueProperty(). AddListener ((obs, ancienneValeur, nouvelleValeur) -> Platform.runLater (() -> items.setPredicate (élément -> élément! = NouvelleValeur))); –