[英]TextField onEdit listener
我正在嘗試在javafx中使用TextField。 場景:我有一個填充有特定對象的列表視圖和一個編輯按鈕來編輯與列表視圖的列表單元關聯的對象。 當我單擊“編輯”按鈕時,它會將我重定向到具有編輯功能的窗格,在其中可以編輯該對象的名稱並使用“保存”按鈕將其保存。 因此,我必須在“保存”按鈕上添加驗證以使其啟用和禁用。 如果我在文本字段中編輯名稱,則應啟用保存按鈕,否則應保持禁用狀態。 我嘗試了如下對文本字段使用不同的方法。
textField.textPorperty.addListener(listener -> {
//Logic to enable disable save button
});
當我使用列表視圖時,此偵聽器為我提供了舊值,作為先前編輯的對象,它不滿足我的條件。 我不能使用
textField.focusedProperty().addListener((observableValue, oldValue, newValue) -> {});
因為它沒有給我預期的行為。
誰能幫我解決這個問題?
您需要實現其他邏輯,以決定對textProperty的更改是否應該更改按鈕的啟用狀態。 這要求:
下面是一個非常簡化的示例(僅供您入門),它將這些基礎知識提取到一個名為BufferedTextInput的專用類中。 緩沖在內部更改:
可以根據需要實現更復雜的邏輯(例如在檢測到更改為原始值時不進行緩沖)。
/**
* Bind disable property of commit/cancel button to actual change.
* http://stackoverflow.com/q/29935643/203657
*/
public class ManualBufferingDemo extends Application {
private Parent getContent() {
ObservableList<Person> persons = FXCollections.observableList(Person.persons(),
person -> new Observable[] {person.lastNameProperty()});
ListView<Person> listView = new ListView<>(persons);
TextField lastName = new TextField();
Consumer<String> committer = text -> System.out.println("committing: " + text);
BufferedTextInput buffer = new BufferedTextInput(lastName, committer);
Button save = new Button("Save");
save.setOnAction(e -> {
buffer.commit();
});
save.disableProperty().bind(Bindings.not(buffer.bufferingProperty()));
Button cancel = new Button("Cancel");
cancel.setOnAction(e -> {
buffer.flush();
});
listView.getSelectionModel().selectedItemProperty().addListener((source, old, current) -> {
buffer.setSubject(current.lastNameProperty());
});
cancel.disableProperty().bind(Bindings.not(buffer.bufferingProperty()));
VBox content = new VBox(listView, lastName, save, cancel);
return content;
}
public static class BufferedTextInput {
private ReadOnlyBooleanWrapper buffering;
private StringProperty value;
private TextField input;
private Consumer<String> committer;
public BufferedTextInput(TextField input, Consumer<String> committer) {
buffering = new ReadOnlyBooleanWrapper(this, "buffering", false);
value = new SimpleStringProperty(this, "");
this.input = input;
this.committer = committer;
input.textProperty().addListener((source, old, current) -> {
updateState(old, current);
});
input.setOnAction(e -> commit());
}
private void updateState(String old, String current) {
if (isBuffering()) return;
if (value.get().equals(current)) return;
setBuffering(true);
}
public void setSubject(StringProperty value) {
this.value = value;
input.setText(value.get());
setBuffering(false);
}
public void commit() {
committer.accept(input.getText());
this.value.set(input.getText());
setBuffering(false);
}
public void flush() {
input.setText(value.get());
setBuffering(false);
}
public boolean isBuffering() {
return buffering.get();
}
public ReadOnlyBooleanProperty bufferingProperty() {
return buffering.getReadOnlyProperty();
}
private void setBuffering(boolean buffer) {
buffering.set(buffer);
}
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(getContent()));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
對於生產用途,這種視圖和模型之間的直接耦合(例如,當需要緩沖以獲得完整的表單時)不夠好,可能需要進一步分離。 請參見臭名昭著的AlbumManager示例的FX改編中的BufferedObjectProperty及其用法(非常粗糙)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.