2017-06-18 113 views
0

我有一個JavaFX ListView。當我點擊列表中的一個項目時,我想要兩個...編輯控件,一個ComboBox和一個TextField,由模型中的相應值填充。無法將JavaFX TextField綁定到ListView值

首先,我的模型:

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

在我的控制,我有:

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

當我點擊就行了,如預期的那樣SimpleObjectProperty被更新,但我的控制現在要做的顯示數據。我錯過了什麼?

回答

1

在進行綁定時,您的綁定綁定到屬於當前收件人的屬性。如果recipient的值發生變化,則例如address.textProperty仍將綁定到前一個值recipientaddressProperty(),而不是新的值。

可以使用監聽器接收方綁定和取消綁定的控件:

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

順便說一句,請注意,你不應該使用鼠標偵聽到選擇變化作出反應:它不會工作,例如,如果用戶使用鍵盤來更改列表視圖中的選擇。你可以用

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

更換recipList.setOnMouseClicked(...)和刪除recipClicked(...)完全。 (事實上​​,你可能不需要recipient可言:你可以用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

,完美做到了。我也不是onMouseClick的粉絲,你也修正了這個問題。你真棒。 :) 非常感謝! – jasondlee