2017-06-18 3 views
0

Ich habe eine JavaFX ListView. Wenn ich auf ein Element in der Liste klicke, möchte ich, dass zwei ... Edit-Steuerelemente, eine ComboBox und ein TextField, mit den entsprechenden Werten aus dem Modell gefüllt werden.Kann JavaFX TextField nicht an ListView-Wert binden

Zuerst mein Modell:

public class Recipient { 
    private final SimpleStringProperty type = new SimpleStringProperty(); 
    private final SimpleStringProperty address = new SimpleStringProperty(); 
    // property getters 
} 

In meinem Controller, ich habe:

public class Controller implements Initializable { 
    @FXML 
    private ComboBox type; 
    @FXML 
    private TextField address; 
    @FXML 
    private ListView<Recipient> recipList; 

    private final ObservableList<String> types = FXCollections.observableArrayList("SMS", "Email"); 
    private final ObservableList<Recipient> recips = FXCollections.observableArrayList(Recipient.DUMMYDATA); 
    private final ObjectProperty<Recipient> recipient = new SimpleObjectProperty<>(); 

    @Override 
    public void initialize(URL url, ResourceBundle rb) { 
     type.setItems(types); 
     recipList.setItems(recips); 
     recipList.setCellFactory((ListView<Recipient> p) -> new ListCell<Recipient>() { 
      @Override 
      public void updateItem(Recipient recip, boolean empty) { 
       super.updateItem(recip, empty); 
       final int index = p.getItems().indexOf(recip); 
       if (index > -1) { 
        setText(String.format("%s - %s", recip.typeProperty().get(), recip.addressProperty().get())); 
       } else { 
        setText(null); 
       } 
      } 
     }); 
     recipient.setValue(new Recipient()); 
     recipList.setOnMouseClicked(event -> recipClicked(event)); 
     type.valueProperty().bindBidirectional(recipient.get().typeProperty()); 
     address.textProperty().bindBidirectional(recipient.get().addressProperty()); 
    } 

    public void recipClicked(MouseEvent event) { 
     final MultipleSelectionModel<Recipient> get = recipList.selectionModelProperty().get(); 
     final Recipient selectedItem = get.getSelectedItem(); 
     recipient.setValue(selectedItem); 
    } 
} 

Wenn ich auf der Liste klicken, wird der SimpleObjectProperty aktualisiert, wie erwartet, aber meine Kontrollen jetzt zeigen die Daten. Was vermisse ich?

Antwort

1

Ihre Bindungen binden an die Eigenschaften des aktuellen Empfängers zum Zeitpunkt der Bindung. Wenn sich der Wert recipient ändert, dann wird beispielsweise address.textProperty immer noch an den addressProperty() des vorherigen Werts recipient gebunden, nicht an den neuen Wert.

Sie einen Zuhörer auf Empfänger verwenden können, um die Kontrollen zu binden und lösen:

recipient.addListener((obs, oldRecipient, newRecipient) -> { 
    if (oldRecipient != null) { 
     type.valueProperty().unbindBidirectional(oldRecipient.typeProperty()); 
     address.textProperty().unbindBidirectional(oldRecipient.addressProperty()); 
    } 
    if (newRecipient != null) { 
     type.valueProperty().bindBidirectional(newRecipient.typeProperty()); 
     address.textProperty().bindBidirectional(newRecipient.addressProperty()); 
    } 
}); 

Als beiseite, beachten Sie, dass Sie keine Maus Zuhörer reagieren auf Veränderungen der Auswahl verwendet werden soll: es nicht funktionieren wird, Wenn der Benutzer beispielsweise die Tastatur zum Ändern der Auswahl in der Listenansicht verwendet. Sie können recipList.setOnMouseClicked(...) mit

recipient.bind(recipList.getSelectionModel().selectedItemProperty()); 

ersetzen und recipClicked(...) vollständig entfernen. (In der Tat könnte man nicht recipient brauchen überhaupt: Sie können es einfach ersetzen mit recipList.getSelectionModel().selectedItemProperty().)

public class Controller implements Initializable { 
    @FXML 
    private ComboBox type; 
    @FXML 
    private TextField address; 
    @FXML 
    private ListView<Recipient> recipList; 

    private final ObservableList<String> types = FXCollections.observableArrayList("SMS", "Email"); 
    private final ObservableList<Recipient> recips = FXCollections.observableArrayList(Recipient.DUMMYDATA); 

    @Override 
    public void initialize(URL url, ResourceBundle rb) { 
     type.setItems(types); 
     recipList.setItems(recips); 
     recipList.setCellFactory((ListView<Recipient> p) -> new ListCell<Recipient>() { 
      @Override 
      public void updateItem(Recipient recip, boolean empty) { 
       super.updateItem(recip, empty); 
       if (empty) { 
        setText(null); 
       } else { 
        setText(String.format("%s - %s", recip.typeProperty().get(), recip.addressProperty().get())); 
       } 
      } 
     }); 
     recipList.getSelectionModel().selectedItemProperty().addListener((obs, oldRecipient, newRecipient) -> { 
      if (oldRecipient != null) { 
       type.valueProperty().unbindBidirectional(oldRecipient.typeProperty()); 
       address.textProperty().unbindBidirectional(oldRecipient.addressProperty()); 
      } 
      if (newRecipient != null) { 
       type.valueProperty().bindBidirectional(newRecipient.typeProperty()); 
       address.textProperty().bindBidirectional(newRecipient.addressProperty()); 
      } 
     }); 
    } 
} 
+0

, dass es tat perfekt. Ich war auch kein Fan von onMouseClicked, und das hast du währenddessen behoben. Du bist unglaublich. :) Danke vielmals! – jasondlee

Verwandte Themen