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);
}
}
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?) –
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é –