2017-05-25 11 views
0

Hallo ich habe ein Problem mit einigen Combo-Box. Ich habe eine Schnittstelle mit vier Kombinationsfeldern und sie verwenden als Elemente die gleiche Liste. Ich habe einen Listener zu einem dieser Kombinationsfelder hinzugefügt, und ich wollte, dass der Listener nur dann ausgeführt wird, wenn ich ein Element auswähle und nicht wenn die Liste geändert wird, aber mit diesem Listener wird er automatisch erneut ausgeführt, wenn ich ein Element aus der Liste entferneEinstellung Listener 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); 

      }); 

so am Ende läuft er diese Zuhörer jedes Mal, wenn ich den Abtrennungs tun, und es endet mit einem Fehler schließlich

+0

Wenn Sie das Element entfernen, die ausgewählt wird, dann wird klar die Auswahl ändern müssen. Was willst du eigentlich hier? (Warum ändern Sie die Liste bei einer Änderung in der Auswahl?) –

+0

Ich möchte auf der ComboBox Wert das Element, das ich ausgewählt habe, aber ich wollte, dass das Element aus der Liste entfernt werden, so wenn ich wieder auf diese Kombination klicken wird Box wird als Optionen angezeigt, alle außer die, die bereits ausgewählt ist –

Antwort

0

Das Problem im Grunde entsteht, weil Sie eine beobachtbare Liste zu ändern am Ende (das selectedItems des Auswahlmodelles), während Eine Änderung in dieser Liste wird verarbeitet. Dies ist ein Fehler in der API, imo. Eine Abhilfe (Hack) ist eine gefilterte Liste zu verwenden, und aktualisieren Sie das Prädikat auf der Liste in einem Platform.runLater(...), um die erste Änderung abgeschlossen ist, bevor es wieder zu ändern zu lassen:

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

Vielleicht ein sauberer Ansatz ist einfach zu deaktivieren Sie die Zelle, die die aktuell ausgewählte Element anzeigt, die zu nah ist, aber nicht ganz die gleiche, 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 das funktioniert, aber aus bestimmten Gründen auf den ersten zwei oder drei Änderungen löscht sogar andere Elemente .. nach einer Weile funktioniert es perfekt, aber ich endende verlieren zwei oder drei Elemente aus die Liste –

+0

FilteredList Elemente = classi.filtered (Element -> Element! = class1.getValue()); class1.setItems (Elemente); class1.valueProperty(). AddListener ((obs, alterWert, neuerWert) -> Platform.runLater (() -> items.setPredicate (item -> item! = NewValue))); –