Java TabeView的非个人文本字段

Java TabeView的非个人文本字段,java,javafx,textfield,Java,Javafx,Textfield,我想在JavaFX中为TableCell使用一个类(TextField)。这个类应该被普遍使用。一周来我一直在寻找解决方案,并在互联网上查看了各种解决方案 我目前的问题是,我可以在TabeView中显示数据,但更改不会到达控制器,即不会保存在数据类中,我也不知道为什么会这样,特别是因为我已经为数据选择器设计了类似的结构,而且它工作得很好 我希望能够控制TabeView中的行为,这也适用于我的类,但是如果数据没有存储在控制器中的数据类中,它又有什么好处呢 目前,我可以在TabeView中查看数据类

我想在JavaFX中为TableCell使用一个类(TextField)。这个类应该被普遍使用。一周来我一直在寻找解决方案,并在互联网上查看了各种解决方案

我目前的问题是,我可以在TabeView中显示数据,但更改不会到达控制器,即不会保存在数据类中,我也不知道为什么会这样,特别是因为我已经为数据选择器设计了类似的结构,而且它工作得很好

我希望能够控制TabeView中的行为,这也适用于我的类,但是如果数据没有存储在控制器中的数据类中,它又有什么好处呢

目前,我可以在TabeView中查看数据类中的值,并根据类中的设置对其进行编辑,但我无法将数据放入控制器中的数据类中

以下是我目前的做法:

控制器

columnCourse.setCellValueFactory(新的PropertyValueFactory(“CourseName”);
setCellFactory(i->new CellClassTextFieldString(columnCourse,20));
setOnEditCommit(e->{System.out.println(“在控制器中提交”);});
TextFieldClass

公共类CellClassTextFieldString扩展了TableCell{
私有最终文本字段文本字段;
私人最终int maxLen;
公共CellClassTextFieldString(表列stringCol,整数maxLen){
this.textField=新的textField();
this.maxLen=maxLen;
this.textField.setTextFormatter(新的TextFormatter(新的StringConverter)(){
@凌驾
公共字符串到字符串(字符串对象){
如果(object==null)返回“”;
if(object.length()>maxLen){
返回object.substring(0,maxLen);
}否则{
返回对象;
}
}
@凌驾
公共字符串fromString(字符串字符串){
if(字符串==null){
返回“”;
}否则{
if(string.length()>maxLen){
返回string.substring(0,maxLen);
}否则{
返回字符串;
}
}
}
}));
editableProperty().bind(stringCol.editableProperty());
contentDisplayProperty().bind(绑定
.when(editableProperty())
.then(仅限ContentDisplay.GRAPHIC_)
。否则(仅限ContentDisplay.TEXT_)
);           
setListener();
}   
@凌驾
受保护的void updateItem(字符串strInput,布尔空){
System.out.println(“updateItem”);
super.updateItem(strInput,空);
if(空){
setText(空);
设置图形(空);
}否则{
this.textField.setText(strInput);
setGraphic(this.textField);
if(strInput==null){
setText(“”);
}否则{
setText(strInput);
}
}   
} 
私有void setListener(){
this.textField.focusedProperty().addListener((可观察、旧值、新值)->{
如果(新值){
System.out.println(“获取焦点”);
}否则{
System.out.println(“失去焦点”);
committedit(textField.getText());
}
});
this.textField.textProperty().addListener((可观察、旧值、新值)->{
System.out.println(“commit:+newValue+”isEditing:+isEditing());
if(newValue.length()>maxLen){
textField.setText(oldValue);
}
});   
this.textField.setOnKeyPressed(新的EventHandler(){
@覆盖公共无效句柄(KeyEvent evt){
if(KeyCode.ESCAPE==evt.getCode()){
System.out.println(“取消编辑”);
取消编辑();
}
if(KeyCode.ENTER==evt.getCode()| | KeyCode.TAB==evt.getCode()){
System.out.println(“提交编辑”);
committedit(textField.getText());
}
}
});
}
}

我可以清楚地注意到的一个问题是contentDisplayProperty的绑定。是否只有在编辑时才需要文本字段?如果是这种情况,则需要使用只读编辑属性而不是可编辑属性进行绑定

contentDisplayProperty().bind(Bindings
                    .when(editingProperty())
                    .then(ContentDisplay.GRAPHIC_ONLY)
                    .otherwise(ContentDisplay.TEXT_ONLY)
            );
下面是可以工作的修改后的单元实现。(至少对我有用:-)

class CellClassTextFieldString扩展了TableCell{
私有文本字段文本字段;
私人最终int maxLen;
公共CellClassTextFieldString(表列stringCol,整数maxLen){
this.maxLen=maxLen;
editableProperty().bind(stringCol.editableProperty());
contentDisplayProperty().bind(绑定
.when(编辑属性())
.then(仅限ContentDisplay.GRAPHIC_)
。否则(仅限ContentDisplay.TEXT_)
);
}
@凌驾
受保护的void updateItem(字符串strInput,布尔空){
System.out.println(“updateItem”);
super.updateItem(strInput,空);
if(空){
setText(空);
设置图形(空);
}否则{
if(isEditing()){
if(textField!=null){
setText(getItem());
}
设置图形(文本字段);
}否则
class CellClassTextFieldString<T> extends TableCell<T, String> {
        private TextField textField;
        private final int maxLen;

        public CellClassTextFieldString(TableColumn<T, String> stringCol, Integer maxLen) {
            this.maxLen = maxLen;
            editableProperty().bind(stringCol.editableProperty());
            contentDisplayProperty().bind(Bindings
                    .when(editingProperty())
                    .then(ContentDisplay.GRAPHIC_ONLY)
                    .otherwise(ContentDisplay.TEXT_ONLY)
            );
        }

        @Override
        protected void updateItem(String strInput, boolean empty) {
            System.out.println("updateItem");
            super.updateItem(strInput, empty);
            if (empty) {
                setText(null);
                setGraphic(null);
            } else {
                if (isEditing()) {
                    if (textField != null) {
                        textField.setText(getItem());
                    }
                    setGraphic(textField);
                } else {
                    setText(getItem());
                }
            }
        }

        @Override
        public final void cancelEdit() {
            super.cancelEdit();
            setText(getItem());
        }

        @Override
        public final void commitEdit(final String newValue) {
            super.commitEdit(newValue);
        }

         @Override
        public final void startEdit() {
             super.startEdit();
             if (textField == null) {
                 createTextField();
             }
             setGraphic(textField);
             textField.setText(getItem());
             textField.selectAll();
             textField.requestFocus();
        }

        private void createTextField() {
            this.textField = new TextField();
            this.textField.setTextFormatter(new TextFormatter<>(new StringConverter<String>() {
                @Override
                public String toString(String object) {
                    if (object == null) return "";

                    if (object.length() > maxLen) {
                        return object.substring(0, maxLen);
                    } else {
                        return object;
                    }
                }

                @Override
                public String fromString(String string) {
                    if (string == null) {
                        return "";
                    } else {
                        if (string.length() > maxLen) {
                            return string.substring(0, maxLen);
                        } else {
                            return string;
                        }
                    }
                }
            }));

            this.textField.focusedProperty().addListener((observable, oldValue, newValue) -> {
                if (!newValue) {
                    System.out.println("lost focus");
                    commitEdit(textField.getText());
                }
            });

            this.textField.textProperty().addListener((observable, oldValue, newValue) -> {
                if (newValue.length() > maxLen) {
                    textField.setText(oldValue);
                }
            });

            this.textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
                @Override
                public void handle(KeyEvent evt) {
                    if (KeyCode.ESCAPE == evt.getCode()) {
                        System.out.println("cancel edit");
                        cancelEdit();
                    }
                    if (KeyCode.ENTER == evt.getCode() || KeyCode.TAB == evt.getCode()) {
                        System.out.println("commit edit");
                        commitEdit(textField.getText());
                    }
                }
            });
        }
    }
columnCourse.setOnEditCommit(e -> {
            System.out.println("Commit in Controller ");
            ( e.getTableView().getItems().get(
                    e.getTablePosition().getRow())
            ).set<Name>(e.getNewValue());
        });