JavaFX2:在TableCell中保存编辑

JavaFX2:在TableCell中保存编辑,javafx,javafx-2,Javafx,Javafx 2,在我的JavaFX程序中,我使用一个TableCell,您可以在其中编辑一个值。如JavaFX页面上的示例所示,我使用此函数保存更改(函数设置在编辑单元的TextField上) textField.setOnKeyReleased(新的EventHandler(){ @重写公共无效句柄(KeyEvent t){ if(组合匹配(t)){ committedit(textField.getText()); }else if(t.getCode()==KeyCode.ESCAPE){ 取消编辑();

在我的JavaFX程序中,我使用一个TableCell,您可以在其中编辑一个值。如JavaFX页面上的示例所示,我使用此函数保存更改(函数设置在编辑单元的TextField上)

textField.setOnKeyReleased(新的EventHandler(){
@重写公共无效句柄(KeyEvent t){
if(组合匹配(t)){
committedit(textField.getText());
}else if(t.getCode()==KeyCode.ESCAPE){
取消编辑();
}
}
当使用ENTER键离开单元格时,该值会被更改/保存,但是当单击另一个单元格离开单元格时,如何更改/保存该值?实际上,该值会被重置

谢谢
Basti

监听文本字段焦点的变化是一种方式。我在文本字段的focusedProperty中添加了一个侦听器。Oracle的示例中没有包含此内容。 [编辑-这里有一个链接,指向另一个方法不同的问题]

private void createTextField(){
textField=新的textField(getItem());
textField.setMinWidth(this.getWidth()-this.getGraphicTextGap()*2);
//检测文本字段焦点的变化。如果失去焦点,我们将采取适当的措施
textField.focusedProperty().addListener(新的ChangeListener()){
public void已更改(observeValue
import javafx.beans.property.ObjectProperty;
导入javafx.beans.value.ChangeListener;
导入javafx.beans.value.observeValue;
导入javafx.collections.ObservableList;
导入javafx.scene.Node;
导入javafx.scene.control.Cell;
导入javafx.scene.control.ComboBox;
导入javafx.scene.control.TextField;
导入javafx.scene.input.KeyCode;
导入javafx.scene.input.KeyEvent;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.layout.HBox;
导入javafx.util.StringConverter;
类细胞发生器{
/***************************************************************************
**私人领域**
**************************************************************************/
私有最终静态StringConverter defaultStringConverter=新StringConverter(){
@凌驾
公共字符串toString(对象t){
返回t==null?null:t.toString();
}
@凌驾
公共对象fromString(字符串){
返回(对象)字符串;
}
};
静态StringConverter defaultStringConverter(){
返回(StringConverter)defaultStringConverter;
}
私有静态字符串getItemText(单元格、StringConverter转换器){
返回转换器==null?cell.getItem()==null?”:cell.getItem().toString()
:converter.toString(cell.getItem());
}
/***************************************************************************
**文本字段方便**
**************************************************************************/
静态void updateItem(最终单元格、最终StringConverter转换器、最终TextField TextField){
updateItem(单元格、转换器、null、null、textField);
}
静态无效更新项(最终单元单元、最终StringConverter转换器、最终HBox HBox、,
最终节点图形、最终文本字段(文本字段){
if(cell.isEmpty()){
cell.setText(null);
cell.setGraphic(空);
}否则{
if(cell.isEditing()){
if(textField!=null){
setText(getItemText(单元格,转换器));
}
cell.setText(null);
如果(图形!=null){
hbox.getChildren().setAll(图形,文本字段);
细胞集落图(hbox);
}否则{
cell.setGraphic(textField);
}
}否则{
setText(getItemText(cell,converter));
cell.setGraphic(图形);
}
}
}
静态无效启动IT(最终电池单元、最终StringConverter转换器、最终HBox HBox、,
最终节点图形、最终文本字段(文本字段){
if(textField!=null){
setText(getItemText(单元格,转换器));
}
cell.setText(null);
如果(图形!=null){
hbox.getChildren().setAll(图形,文本字段);
细胞集落图(hbox);
}否则{
cell.setGraphic(textField);
}
textField.selectAll();
//请求焦点,以便按键输入可以立即进入
//文本字段(见RT-28132)
textField.requestFocus();
}
静态void cancelEdit(单元、最终StringConverter转换器、节点图形){
setText(getItemText(cell,converter));
cell.setGraphic(图形);
}
静态TextField createTextField(最终单元格、最终StringConverter转换器){
final TextField TextField=新的TextField(getItemText(单元格,转换器));
EditingCell单元格编辑=(EditingCell)单元格;
textField.setOnMouseExited(事件->{
if(converter==null){
抛出新的IllegalStateException(“试图将文本输入转换为对象,但已提供”
+“StringConverter为空。请确保设置StringConverter”
+“在你的细胞工厂里。”);
}
committedit(converter.fromString(textField.getText());
});
textField.addEventFilter(按下KeyEvent.KEY,事件->{
if(event.getCode()==KeyCode.ESCAPE){
cell.cancelEdit();
event.consume();
}else if(event.getCode()==KeyCode.RIGHT){
cellEdit.getTableView().getSelectionModel().selectRightCell();
event.consume();
}else if(event.getCode()==KeyCode.LEFT){
cellEdit.getTableView().getSelectionModel().selectLeftCell();
event.consume();
}else if(event.getCode()==KeyCode.UP){
cellEdit.getTableView().getSelectionModel().SelectOverCell();
event.consume();
}else if(event.getCode()==KeyCode.DOWN){
cellEdit.getTableView().getSelectionModel().selectBelowCell();
event.consume();
}else if(event.getCode()==KeyCod
textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
    @Override public void handle(KeyEvent t) {
    if (combo.match(t)) {
        commitEdit(textField.getText());
    } else if (t.getCode() == KeyCode.ESCAPE) {
        cancelEdit();
    }
 }
private void createTextField() {
        textField = new TextField(getItem());
        textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);

        // Detect a change in focus on the text field.. If we lose the focus we take appropriate action
        textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                if(!newValue.booleanValue())
                    commitEdit(textField.getText());
            }
        } );
        textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
            @Override public void handle(KeyEvent t) {
                if (t.getCode() == KeyCode.ENTER) {
                    commitEdit(textField.getText());
                } else if (t.getCode() == KeyCode.ESCAPE) {
                    cancelEdit();
                }
            }
        });
    }
  import javafx.beans.property.ObjectProperty;
  import javafx.beans.value.ChangeListener;
  import javafx.beans.value.ObservableValue;
  import javafx.collections.ObservableList;
    import javafx.scene.Node;
  import javafx.scene.control.Cell;
  import javafx.scene.control.ComboBox;
  import javafx.scene.control.TextField;
  import javafx.scene.input.KeyCode;
 import javafx.scene.input.KeyEvent;
 import javafx.scene.input.MouseEvent;
 import javafx.scene.layout.HBox;
import javafx.util.StringConverter;

class CellGenerator {

/***************************************************************************
 * * Private fields * *
 **************************************************************************/
private final static StringConverter defaultStringConverter = new StringConverter<Object>() {
    @Override
    public String toString(Object t) {
        return t == null ? null : t.toString();
    }

    @Override
    public Object fromString(String string) {
        return (Object) string;
    }
};

static <T> StringConverter<T> defaultStringConverter() {
    return (StringConverter<T>) defaultStringConverter;
}

private static <T> String getItemText(Cell<T> cell, StringConverter<T> converter) {
    return converter == null ? cell.getItem() == null ? "" : cell.getItem().toString()
            : converter.toString(cell.getItem());
}

/***************************************************************************
 * * TextField convenience * *
 **************************************************************************/
static <T> void updateItem(final Cell<T> cell, final StringConverter<T> converter, final TextField textField) {
    updateItem(cell, converter, null, null, textField);
}

static <T> void updateItem(final Cell<T> cell, final StringConverter<T> converter, final HBox hbox,
        final Node graphic, final TextField textField) {
    if (cell.isEmpty()) {
        cell.setText(null);
        cell.setGraphic(null);
    } else {
        if (cell.isEditing()) {
            if (textField != null) {
                textField.setText(getItemText(cell, converter));
            }
            cell.setText(null);
            if (graphic != null) {
                hbox.getChildren().setAll(graphic, textField);
                cell.setGraphic(hbox);
            } else {
                cell.setGraphic(textField);
            }
        } else {
            cell.setText(getItemText(cell, converter));
            cell.setGraphic(graphic);
        }
    }
}

static <T> void startEdit(final Cell<T> cell, final StringConverter<T> converter, final HBox hbox,
        final Node graphic, final TextField textField) {
    if (textField != null) {
        textField.setText(getItemText(cell, converter));
    }
    cell.setText(null);
    if (graphic != null) {
        hbox.getChildren().setAll(graphic, textField);
        cell.setGraphic(hbox);
    } else {
        cell.setGraphic(textField);
    }
    textField.selectAll();
    // requesting focus so that key input can immediately go into the
    // TextField (see RT-28132)
    textField.requestFocus();
}

static <T> void cancelEdit(Cell<T> cell, final StringConverter<T> converter, Node graphic) {
    cell.setText(getItemText(cell, converter));
    cell.setGraphic(graphic);

}

static <T> TextField createTextField(final Cell<T> cell, final StringConverter<T> converter) {

    final TextField textField = new TextField(getItemText(cell, converter));
    EdittingCell cellEdit=(EdittingCell)cell;
    textField.setOnMouseExited(event -> {

        if (converter == null) {
            throw new IllegalStateException("Attempting to convert text input into Object, but provided "
                    + "StringConverter is null. Be sure to set a StringConverter "
                    + "in your cell factory.");
        }

        cell.commitEdit(converter.fromString(textField.getText()));

    });

    textField.addEventFilter(KeyEvent.KEY_PRESSED, event -> {

        if (event.getCode() == KeyCode.ESCAPE) {
            cell.cancelEdit();
            event.consume();
        } else if (event.getCode() == KeyCode.RIGHT) {
            cellEdit.getTableView().getSelectionModel().selectRightCell();
            event.consume();
        } else if (event.getCode() == KeyCode.LEFT) {
            cellEdit.getTableView().getSelectionModel().selectLeftCell();
            event.consume();
        } else if (event.getCode() == KeyCode.UP) {
            cellEdit.getTableView().getSelectionModel().selectAboveCell();
            event.consume();
        } else if (event.getCode() == KeyCode.DOWN) {
            cellEdit.getTableView().getSelectionModel().selectBelowCell();
            event.consume();
        } else if (event.getCode() == KeyCode.ENTER) {
            if (converter == null) {
                throw new IllegalStateException("Attempting to convert text input into Object, but provided "
                        + "StringConverter is null. Be sure to set a StringConverter "
                        + "in your cell factory.");
            }

            cell.commitEdit(converter.fromString(textField.getText()));

            event.consume();
        }
        else if (event.getCode() == KeyCode.TAB) {

            cell.commitEdit(converter.fromString(textField.getText()));

            cellEdit.setNextColumn(event);

            event.consume();
        }
    });

    return textField;
}}
  import java.util.ArrayList;
  import java.util.List;

  import javafx.beans.property.ObjectProperty;
  import javafx.beans.property.SimpleObjectProperty;
  import javafx.collections.FXCollections;
  import javafx.collections.ObservableList;
  import javafx.event.EventHandler;
  import javafx.scene.control.*;
   import javafx.scene.input.KeyCode;
   import javafx.scene.input.KeyEvent;
   import javafx.util.Callback;
   import javafx.util.StringConverter;
   import javafx.util.converter.DefaultStringConverter;

 public class EdittingCell<S, T> extends TableCell<S, T> {

public static <S> Callback<TableColumn<S, String>, TableCell<S, String>> 
forTableColumn() {
    return forTableColumn(new DefaultStringConverter());
}

public static <S, T> Callback<TableColumn<S, T>, TableCell<S, T>> 
forTableColumn(
        final StringConverter<T> converter) {
    return new Callback<TableColumn<S, T>, TableCell<S, T>>() {
        @Override
        public TableCell<S, T> call(TableColumn<S, T> list) {
            return new EdittingCell<S, T>(converter);
        }
    };
}

public static <S, T> Callback<TableColumn<S, T>, TableCell<S, T>> 
forTableColumn(final StringConverter<T> converter,
        final boolean isFieldEditable) {
    return new Callback<TableColumn<S, T>, TableCell<S, T>>() {
        @Override
        public TableCell<S, T> call(TableColumn<S, T> list) {
            return new EdittingCell<S, T>(converter, isFieldEditable);
        }
    };
}

/***************************************************************************
 * * Fields * *
 **************************************************************************/
public TextField textField;
private static int currentRow = -1;
private static int control = 0;

public EdittingCell() {
    this(null);
    textField = CellGenerator.createTextField(this, getConverter());
}

public EdittingCell(StringConverter<T> converter) {

    this.getStyleClass().add("text-field-table-cell");

    setConverter(converter);
    textField = CellGenerator.createTextField(this, getConverter());
    // textField.setEditable(false);

}

public EdittingCell(StringConverter<T> converter, boolean isFieldEditable) {

    this.getStyleClass().add("text-field-table-cell");

    setConverter(converter);
    textField = CellGenerator.createTextField(this, getConverter());
    textField.setEditable(isFieldEditable);

}

/***************************************************************************
 * * Properties * *
 **************************************************************************/
// --- converter
private ObjectProperty<StringConverter<T>> converter = new SimpleObjectProperty<StringConverter<T>>(this,
        "converter");

public final ObjectProperty<StringConverter<T>> converterProperty() {
    return converter;
}

public TextField getTextFiedCell() {
    return textField;
}

public final void setConverter(StringConverter<T> value) {
    converterProperty().set(value);
}

public final StringConverter<T> getConverter() {
    return converterProperty().get();
}

@Override
public void startEdit() {
    if (!isEditable() || !getTableView().isEditable() || !getTableColumn().isEditable()) {
        return;
    }
    super.startEdit();
    if (isEditing()) {

        CellGenerator.startEdit(this, getConverter(), null, null, textField);
    }
}

@Override
public void cancelEdit() {
    super.cancelEdit();
    CellGenerator.cancelEdit(this, getConverter(), null);
}

/** {@inheritDoc} */
@Override
public void updateItem(T item, boolean empty) {
    super.updateItem(item, empty);
    CellGenerator.updateItem(this, getConverter(), null, null, textField);
    // System.out.println("Silas");
}

public TableView<S> getContextTableView() {

    return getTableView();
}

public void setNextColumn(KeyEvent event) {
    TableColumn nextColumn = getNextColumn(!event.isShiftDown());

    if (nextColumn != null) {

        // Get Selected index to reset current editable row
        int selectedRow = getTableRow().getIndex();
        // Set row that serves as a control for tapping through
        if (currentRow == -1) {
            currentRow = getTableRow().getIndex();
        }
        // Reset editing upon selection change row
        if (currentRow != selectedRow) {
            currentRow = selectedRow;
        }

        int colSize = getTableView().getColumns().size();
        int colindex = getTableView().getColumns().indexOf(nextColumn);

        if (colindex == colSize - 1) {
            control++;
        }
        if (control > 0 && colindex == 0) {
            currentRow++;
        }

        if (getTableView().getItems().size() > currentRow) {
            getTableView().edit(currentRow, nextColumn);
            // getTableView().getSelectionModel().select(currentRow,
            // nextColumn);
        } else {
            currentRow = 0;
            // getTableView().getSelectionModel().select(currentRow,
            // nextColumn);
            getTableView().edit(currentRow, nextColumn);
        }
    }
}

private TableColumn<S, ?> getNextColumn(boolean forward) {

    List<TableColumn<S, ?>> columns = new ArrayList<>();

    for (TableColumn<S, ?> column : getTableView().getColumns()) {

        columns.addAll(getLeaves(column));

    }

    // There is no other column that supports editing.

    if (columns.size() < 2) {
        return null;
    }
    int currentIndex = columns.indexOf(getTableColumn());
    int nextIndex = currentIndex;
    if (forward) {
        nextIndex++;
        if (nextIndex > columns.size() - 1) {
            nextIndex = 0;

        }
    } else {
        nextIndex--;
        if (nextIndex < 0) {

            nextIndex = columns.size() - 1;
        }

    }
    return columns.get(nextIndex);
}

private ObservableList<TableColumn<S, ?>> getLeaves(TableColumn<S, ?> column2) {
    ObservableList<TableColumn<S, ?>> columns = FXCollections.observableArrayList();
    if (column2.getColumns().isEmpty()) {
        // We only want the leaves that are editable.
        if (column2.isEditable()) {
            columns.addAll(column2);
        }
        return columns;
    } else {
        for (TableColumn<S, ?> column : column2.getColumns()) {
            columns.addAll(getLeaves(column));
        }
        return columns;
    }

}
    TableColumn<NewInvoice, BigDecimal> quantityCol = new 
   TableColumn<NewInvoice, BigDecimal>("Quantity");
    quantityCol.setCellValueFactory(cellData -> 
   cellData.getValue().quantityProperty());
    quantityCol.setCellFactory(EdittingCell.forTableColumn( new 
   BigDecimalStringConverter()));
    quantityCol.setStyle("-fx-alignment:CENTER-RIGHT;");
    quantityCol.setOnEditCommit(new EventHandler<CellEditEvent<NewInvoice, 
   BigDecimal>>() {
        @Override
        public void handle(CellEditEvent<NewInvoice, BigDecimal> t) {
     t.getTableView().getItems().get(t.getTablePosition().getRow()
   ).setQuantity(t.getNewValue());
        }
    });