private void createTextField() {
        textField = new TextField(getString());
        textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
        textField.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent t) {
                if (t.getCode() == KeyCode.ENTER) {
                    commitHelper(false);
                } else if (t.getCode() == KeyCode.ESCAPE) {
                    cancelEdit();
                } else if (t.getCode() == KeyCode.TAB) {
                    commitHelper(false);
                     
                    TableColumn nextColumn = getNextColumn(!t.isShiftDown());
                    if (nextColumn != null) {
                        getTableView().edit(getTableRow().getIndex(), nextColumn);
                    }
                }
            }
        });
        textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                //This focus listener fires at the end of cell editing when focus is lost
                //and when enter is pressed (because that causes the text field to lose focus).
                //The problem is that if enter is pressed then cancelEdit is called before this
                //listener runs and therefore the text field has been cleaned up. If the
                //text field is null we don't commit the edit. This has the useful side effect
                //of stopping the double commit.
                if (!newValue && textField != null) {
                    commitHelper(true);
                }
            }
        });
    }