How to commit when clicking outside an editable TableView cell in JavaFX?

后端 未结 4 847
清歌不尽
清歌不尽 2020-12-29 10:25

I have a table cell factory responsible for creating an editable cell in a JavaFX TableView.

I\'m trying to implement some added functionality to the tableview so th

4条回答
  •  难免孤独
    2020-12-29 11:08

    I created my own workaround (but for JavaFX 2). Main idea - transform cancelEdit() to commitEdit(). With possible validation of committed text via validator.

    /** Validator. */
    public interface TextColumnValidator {
        boolean valid(T rowVal, String newVal);
    }
    
    /**
     * Special table text field cell that commit its content on focus lost.
     */
    public class TextFieldTableCellEx extends TextFieldTableCell {
        /** */
        private final TextColumnValidator validator;
        /** */
        private boolean cancelling;
        /** */
        private boolean hardCancel;
        /** */
        private String curTxt = "";
    
        /** Create cell factory. */
        public static  Callback, TableCell>
            cellFactory(final TextColumnValidator validator) {
                return new Callback, TableCell>() {
                    @Override public TableCell call(TableColumn col) {
                        return new TextFieldTableCellEx<>(validator);
                    }
                };
        }
    
        /**
         * Text field cell constructor.
         *
         * @param validator Input text validator.
         */
        private TextFieldTableCellEx(TextColumnValidator validator) {
            this.validator = validator;
        }
    
        /** {@inheritDoc} */
        @Override public void startEdit() {
            super.startEdit();
    
            curTxt = "";
    
            hardCancel = false;
    
            Node g = getGraphic();
    
            if (g != null) {
                final TextField tf = (TextField)g;
    
                tf.textProperty().addListener(new ChangeListener() {
                    @Override public void changed(ObservableValue val, String oldVal, String newVal) {
                        curTxt = newVal;
                    }
                });
    
                tf.setOnKeyReleased(new EventHandler() {
                    @Override public void handle(KeyEvent evt) {
                        if (KeyCode.ENTER == evt.getCode())
                            cancelEdit();
                        else if (KeyCode.ESCAPE == evt.getCode()) {
                            hardCancel = true;
    
                            cancelEdit();
                        }
                    }
                });
    
                // Special hack for editable TextFieldTableCell.
                // Cancel edit when focus lost from text field, but do not cancel if focus lost to VirtualFlow.
                tf.focusedProperty().addListener(new ChangeListener() {
                    @Override public void changed(ObservableValue val, Boolean oldVal, Boolean newVal) {
                        Node fo = getScene().getFocusOwner();
    
                        if (!newVal) {
                            if (fo instanceof VirtualFlow) {
                                if (fo.getParent().getParent() != getTableView())
                                    cancelEdit();
                            }
                            else
                                cancelEdit();
                        }
                    }
                });
    
                Platform.runLater(new Runnable() {
                    @Override public void run() {
                        tf.requestFocus();
                    }
                });
            }
        }
    
        /** {@inheritDoc} */
        @Override public void cancelEdit() {
            if (cancelling)
                super.cancelEdit();
            else
                try {
                    cancelling = true;
    
                    if (hardCancel || curTxt.trim().isEmpty())
                        super.cancelEdit();
                    else if (validator.valid(getTableView().getSelectionModel().getSelectedItem(), curTxt))
                        commitEdit(curTxt);
                    else
                        super.cancelEdit();
                }
                finally {
                    cancelling = false;
                }
        }
    }
    

    Update: this code was written as a part of Apache Ignite Schema Import GUI Utility. See full version of TableCell code: https://github.com/apache/ignite/blob/ignite-1.9/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/Controls.java

    Also you could build this utility (it is a very simple utility with 2 screens) and play with it under Java7/javaFx2 & Java8/JavaFx8.

    I tested - it works under both of them.

提交回复
热议问题