Search code examples
javafxlistenertableview

JavaFX tab through editable cells


I have defined my own editable cell for a TableView. Everything works great but I want to be able to tab through the cells. Say I'm in cell [2,2] on a tab press I want the selected cell to go to [3,2]. Is this possible? How should I go about achieving this? Should I add a listener to the TableCell or the TableColumn?

Here is my custom TableCell

class EditingCell extends TableCell<Student, String> {

   private TextField textField;

   public EditingCell(Assignment assign) {
       this.setTooltip(new Tooltip(assign.getMaxPoints() + " pts max"));
   }

   @Override
   public void startEdit() {
       if (!isEmpty()) {
           super.startEdit();
           createTextField();
           setText(null);
           setGraphic(textField);
           textField.selectAll();
       }
   }

   @Override
   public void cancelEdit() {
       super.cancelEdit();

       setText((String) getItem());
       setGraphic(null);
   }

   @Override
   public void updateItem(String 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);
           }
       }
   }

   private void createTextField() {
       textField = new TextField(getString());
       textField.setMinWidth(this.getWidth() - this.getGraphicTextGap()* 2);
       textField.focusedProperty().addListener(new ChangeListener<Boolean>(){
           @Override
           public void changed(ObservableValue<? extends Boolean> arg0, 
               Boolean arg1, Boolean arg2) {
                if (!arg2) {
                    commitEdit(textField.getText());
                }
            }
        });
    }

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

Solution

  • You can achieve this by adding a KeyListener to your textField. Try adding the following code to your createTextField()

    textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
       @Override
       public void handle(KeyEvent t) {
           if (t.getCode() == KeyCode.ENTER) {
               commitEdit(Integer.parseInt(textField.getText()));
           } else if (t.getCode() == KeyCode.ESCAPE) {
               cancelEdit();
           } else if (t.getCode() == KeyCode.TAB) {
               commitEdit(Integer.parseInt(textField.getText()));
               TableColumn nextColumn = getNextColumn(!t.isShiftDown());
               if (nextColumn != null) {
                   getTableView().edit(getTableRow().getIndex(), nextColumn);
               }
           }
       }
    });
    

    There are a few more things that you will have to take care of. For a complete example, please follow

    https://gist.github.com/abhinayagarwal/9383881