微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

TabelView 的通用文本字段

如何解决TabelView 的通用文本字段

我想在 JavaFX 中为 TableCell 使用一个类 (TextField)。该类应该被普遍使用。找了一个星期的解决方法,在网上看了各种解决方法

我目前的问题是我可以在 TabelView 中显示数据,但是更改没有到达控制器,即没有保存在数据类中,我不知道为什么会这样,特别是因为我已经为数据选择器设计了一个类似的结构,而且效果很好。

我希望能够控制 TabelView 中的行为并且这也适用于我的类,但是如果数据没有存储在控制器的数据类中,它有什么用?

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

到目前为止,这是我的方法

控制器

columnCourse.setCellValueFactory(new PropertyValueFactory<>("CourseName"));
columnCourse.setCellFactory(i -> new CellClasstextFieldString(columnCourse,20));
columnCourse.setonEditCommit(e -> { System.out.println("Commit in Controller ");; });

TextFieldClass

public class CellClasstextFieldString<T> extends TableCell<T,String> {
    
    private final TextField textField;
    private final int maxLen;
    
    public  CellClasstextFieldString(TableColumn<T,String> stringCol,Integer maxLen) {   

        this.textField = new TextField();
        this.maxLen = maxLen;
        
        
        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;
                    }
                }
            }
            
        }));
        
        
       
    editableproperty().bind(stringCol.editableproperty());
    
        
        
    contentdisplayproperty().bind(Bindings
        .when(editableproperty())
                .then(Contentdisplay.GRAPHIC_ONLY)
                .otherwise(Contentdisplay.TEXT_ONLY)
    );           
        
        setListener () ;

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

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

                System.out.println("comit : " + newValue + "isEditing : " + isEditing());
                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());
                }
            }
        });
    }
}

解决方法

我可以清楚地注意到一个问题是 contentDisplayProperty 的绑定。是否仅在编辑时才需要 textField?如果是这种情况,您需要绑定只读编辑属性而不是可编辑属性。

contentDisplayProperty().bind(Bindings
                    .when(editingProperty())
                    .then(ContentDisplay.GRAPHIC_ONLY)
                    .otherwise(ContentDisplay.TEXT_ONLY)
            );

以下是可以工作的修改后的单元格实现。 (至少它对我有用:-))

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。