Java TextField OneEdit侦听器
我正在尝试在javafx中使用TextField。 场景:我使用特定对象填充列表视图,并使用编辑按钮编辑与列表视图的列表单元格关联的对象。 当我点击“编辑”按钮时,它会将我重定向到一个具有编辑功能的窗格,在那里我可以编辑该对象的名称并使用“保存”按钮保存它。 所以我必须在save按钮上进行验证,使其启用和禁用。 如果在文本字段中编辑名称,则应启用“保存”按钮,否则应保持禁用状态。 我已经尝试在文本字段上使用不同的方法,如下所示Java TextField OneEdit侦听器,java,javafx-8,Java,Javafx 8,我正在尝试在javafx中使用TextField。 场景:我使用特定对象填充列表视图,并使用编辑按钮编辑与列表视图的列表单元格关联的对象。 当我点击“编辑”按钮时,它会将我重定向到一个具有编辑功能的窗格,在那里我可以编辑该对象的名称并使用“保存”按钮保存它。 所以我必须在save按钮上进行验证,使其启用和禁用。 如果在文本字段中编辑名称,则应启用“保存”按钮,否则应保持禁用状态。 我已经尝试在文本字段上使用不同的方法,如下所示 textField.textPorperty.addListener
textField.textPorperty.addListener(listener -> {
//Logic to enable disable save button
});
当我使用列表视图时,此侦听器将旧值作为以前编辑的对象提供给我,该对象不满足我的条件。
我不能用
textField.focusedProperty().addListener((observableValue, oldValue, newValue) -> {});
因为它没有给我预期的行为
有人能帮我解决这个问题吗 您需要实现额外的逻辑来决定对textProperty的更改是否应更改按钮的启用状态。这需要:
- 对初始值的引用(将文本设置为输入时,f.i.更改列表中的选择时)
- 保持启用状态的布尔属性(低于它的称为缓冲)
- 文本字段的侦听器,可根据需要更新启用状态
- 如果设置了“主题”值或提交/放弃了更改,则设置为false
- 在第一次更改文本字段时收到通知时设置为true
/**
* 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);
}
}
/**
*将提交/取消按钮的禁用属性绑定到实际更改。
* http://stackoverflow.com/q/29935643/203657
*/
公共类ManualBufferingDemo扩展应用程序{
私有父getContent(){
ObservableList persons=FXCollections.ObservableList(Person.persons(),
person->new Observable[]{person.lastNameProperty()});
ListView ListView=新的ListView(人);
TextField lastName=新的TextField();
消费者提交者=text->System.out.println(“提交:+text”);
BufferedTimePut buffer=新的BufferedTimePut(姓氏,提交人);
按钮保存=新按钮(“保存”);
save.setOnAction(e->{
commit();
});
save.disableProperty().bind(Bindings.not(buffer.bufferingProperty());
按钮取消=新按钮(“取消”);
取消设置操作(e->{
buffer.flush();
});
listView.getSelectionModel().SelectEditeProperty().addListener((源、旧、当前)->{
buffer.setSubject(current.lastNameProperty());
});
cancel.disableProperty().bind(Bindings.not(buffer.bufferingProperty());
VBox内容=新的VBox(列表视图、姓氏、保存、取消);
返回内容;
}
公共静态类缓冲输出{
私有ReadOnlyBooleanWrapper缓冲;
私有财产价值;
私有文本字段输入;
私人消费者委员会;
公共缓冲输入(文本字段输入,消费者提交者){
缓冲=新的ReadOnlyBooleanWrapper(此“缓冲”,false);
值=新的SimpleStringProperty(此“”);
这个输入=输入;
this.committer=提交者;
input.textProperty().addListener((源、旧、当前)->{
不动产(旧的、现有的);
});
setOnAction(e->commit());
}
私有void updateState(字符串旧,字符串当前){
if(isBuffering())返回;
if(value.get().equals(current))返回;
挫折(真);
}
public void setSubject(StringProperty值){
这个值=值;
input.setText(value.get());
挫折(假);
}
公共无效提交(){
accept(input.getText());
this.value.set(input.getText());
挫折(假);
}
公共图书馆{
input.setText(value.get());
挫折(假);
}
公共布尔值isBuffering(){
return buffering.get();
}
public ReadOnlyBooleanProperty bufferingProperty(){
返回buffering.getReadOnlyProperty();
}
私有void setBuffering(布尔缓冲区){
缓冲设置(buffer);
}
}
@凌驾
public void start(Stage primaryStage)引发异常{
setScene(新场景(getContent());
primaryStage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}
对于生产使用,视图和模型之间的这种直接耦合(f.i.当需要完整表单的缓冲时)不够好,可能需要进一步分离。在FX改编的臭名昭著的例子(非常粗糙)中,请看它的用法,如果初始文本是“发出的”,它被改变为“发行”,然后返回“发行”。按钮是否保持启用状态?如果文本已发布更改为发布-按钮启用如果再次更改为发布而未保存以前更改的文本,则应保持禁用状态。