Domanda

Is there a way to make TableView in javafx to act just like JTable in swing?

The current procedure in TableView edit a cell content is:

  1. Select the cell.
  2. Pressing Enter on the Cell to get in Edit mode.
  3. Typing.
  4. Pressing Enter to commit edit.

while in jtable is much easier; you don't have to press enter to edit; you can edit directly.

Any ideas to let javafx table view act like jtable in this point?

È stato utile?

Soluzione

I do it with a bunch of listeners. I'll add snips of my code since the columns won't really apply to you.

public class DataTable extends TableView<LineItem> {
    private final Data data;
    //used for keyreleased in table to put table in editing state and remember which key was    pressed
    private String lastKey = null;
    /** makes a table 
     * @param data The Data structure
     */
    public DataTable(Data data){
        super(data.lines);
        this.data = data;
        setEditable(true);
        //cut out my deleted lines stack but left some code because has to handle del in textfield

        Callback<TableColumn<LineItem,String>, TableCell<LineItem,String>> txtCellFactory = 
                (TableColumn<LineItem,String> p) -> {return new EditingCell();};

        TableColumn<LineItem,String> lineNoCol = new TableColumn<>("Line");
        lineNoCol.setCellValueFactory(new PropertyValueFactory<>("LineNo"));
        lineNoCol.setCellFactory(txtCellFactory);
        lineNoCol.setOnEditCommit((TableColumn.CellEditEvent<LineItem, String> evt) -> {
            evt.getTableView().getItems().get(evt.getTablePosition().getRow())
                    .setLineNo(evt.getNewValue());
        });
//more columns

/////  This puts it in editing state and remebers the key pressed for the textfield
        setOnKeyPressed((KeyEvent t) -> {
            TablePosition tp;
            if (!t.isControlDown() &&
                    (t.getCode().isLetterKey() || t.getCode().isDigitKey())) {
                lastKey = t.getText();
                tp = getFocusModel().getFocusedCell();
                edit(tp.getRow(),tp.getTableColumn());
                lastKey = null;
            }
        });

        addEventFilter(KeyEvent.KEY_PRESSED, (KeyEvent t) -> {
            if (getEditingCell() == null && t.getCode() == KeyCode.ENTER) {
                if (t.isShiftDown()) {
                    getSelectionModel().selectAboveCell();
                } else {
                    getSelectionModel().selectBelowCell();
                }
                t.consume();
            }

            if (t.isControlDown() && t.getCode() == KeyCode.TAB) {
                if (t.isShiftDown()) {
                    getSelectionModel().selectLeftCell();
                } else {
                    getSelectionModel().selectRightCell();
                }
                t.consume();
            }
        });

        setOnKeyReleased((KeyEvent t) -> {
            TablePosition tp;
            switch (t.getCode()) {
                case INSERT:
                    data.lines.add(new LineItem());//maybe try adding at position
                    getSelectionModel().selectLast();
                    break;
                case DELETE:
                    //textfield has to consume this so it doesn't reach here.
                    tp = getSelectionModel().getSelectedCells().get(0);
                    if (tp.getTableColumn() == lineNoCol) {
                        deletedLines.push(data.lines.remove(tp.getRow()));
                        //todo reselect something
                    } else { //maybe delete cell value
                    }
                    break;
                case Z:
                    if (t.isControlDown()) {
                        if (!deletedLines.isEmpty()) {
                            data.lines.add(deletedLines.pop());
                            //todo re-sort etc
                        }
                    }
            }
        });
    }

    private class EditingCell extends TableCell {//no type for now

        private TextField textField;

        @Override
        public void startEdit() {
            if (!isEmpty()) {
                super.startEdit();
                createTextField();
                setText(null);
                setGraphic(textField);
                Platform.runLater(() -> {//without this space erases text, f2 doesn't
                    textField.requestFocus();//also selects
                });
                if (lastKey != null) {
                    textField.setText(lastKey);
                    Platform.runLater(() -> {
                        textField.deselect();
                        textField.end();
                    });
                }
            }
        }

        @Override
        public void cancelEdit() {
            super.cancelEdit();
            try {
                setText(getItem().toString());
            } catch (Exception e) {}
            setGraphic(null);
        }

        @Override
        public void updateItem(Object item, boolean empty) {
            super.updateItem(item, empty);

            if (empty) {
                setText(null);
                setGraphic(null);
            } else if (isEditing()) {
                if (textField != null) {
                    textField.setText(getString());
                }
                setText(null);
                setGraphic(textField);
            } else {
                setText(getString());
                setGraphic(null);
                //not applicable but shows how to align columns
                if (getTableColumn().getText().equals("Amount"))
                    setAlignment(Pos.CENTER_RIGHT);
            }
        } 

        private void createTextField() {
            textField = new TextField(getString());
            //setPadding(Insets.EMPTY);//screws up table cell for after
            textField.setPadding(new Insets(0,0,0,5));
            textField.setPrefHeight(this.getHeight()-2);//border hgt??

            textField.focusedProperty().addListener(
                    (ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) -> {
                if (!arg2) commitEdit(textField.getText());
            });

            textField.setOnKeyReleased((KeyEvent t) -> {
                if (t.getCode() == KeyCode.ENTER) {
                    commitEdit(textField.getText());
                    EditingCell.this.getTableView().requestFocus();//why does it lose focus??
                    EditingCell.this.getTableView().getSelectionModel().selectBelowCell();
                }
                else if (t.getCode() == KeyCode.RIGHT) {//dont really like this
                    if (textField.getCaretPosition() >= textField.getLength()){
                        commitEdit(textField.getText());
                        EditingCell.this.getTableView().requestFocus();//why does it lose focus??
                        EditingCell.this.getTableView().getSelectionModel().selectRightCell();
                    }
                }
                else if (t.getCode() == KeyCode.UP) {//moves caret to 0
                    if (textField.getCaretPosition() == 0){
                        commitEdit(textField.getText());
                        EditingCell.this.getTableView().requestFocus();//why does it lose focus??
                        EditingCell.this.getTableView().getSelectionModel().selectAboveCell();
                    }
                }
                else if (t.getCode() == KeyCode.DOWN) {
                    if (textField.getCaretPosition() >= textField.getLength()){
                        commitEdit(textField.getText());
                        EditingCell.this.getTableView().requestFocus();//why does it lose focus??
                        EditingCell.this.getTableView().getSelectionModel().selectBelowCell();
                    }
                }
                else if (t.getCode() == KeyCode.ESCAPE) {
                    cancelEdit();
                }
            });

            textField.addEventFilter(KeyEvent.KEY_RELEASED, (KeyEvent t) -> {
                if (t.getCode() == KeyCode.DELETE) {
                    t.consume();//stop from deleting line in table keyevent
                }
            });
        }

        private String getString() {
            return getItem() == null ? "" : getItem().toString();
        }
    }

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top