2011-10-23 8 views
1

私のJavaFXプログラムでは、値を編集できるTableCellを使用します。 JavaFXのページ"Example"上の例で示したように、私は(関数がエディット・セルでのTextFieldに設定されている)JavaFX 2:TableCellで編集を保存

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(); 
    } 
} 

セルを残してENTER使用して、値が変更された変更を保存するには、この機能を使用します/別のセルをクリックしてセルを離れるときに、値を変更/保存するにはどうすればよいですか?実際には値はリセットされます。

おかげでは、TextFieldにフォーカスの変更を聴く バスティ

答えて

2

が一つの方法です。私は、TextFieldのfocusedPropertyにリスナーを追加しました。 Oracleの例にはこれは含まれていませんでした。 [編集 - ここでは異なるアプローチUITableView - Better Editing through Binding?を持っている別の質問へのリンクがある]

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(); 
       } 
      } 
     }); 
    } 
+2

私はdisli私はより良い方法は、コントロールを基になるデータモデルにバインドし、すべてのイベントのトラップ、処理、およびメソッドのオーバーライドで行うことだと思います。 – jkaufmann

+0

ありがとうございます。あなたがより良いやり方を分かち合うことができればそれはいいでしょう、それはまさにそれ、私が探しているものでしょう。 – McPepper

+0

わかりやすくするために、「TableViewの編集をより良くするためにバインディングを使用する方法」という質問を投稿し、それに答えます。しかし、この質問の目的のために、私は答えがfocusedProperty()変更イベントをトラップすると考えています。完了したら、この質問にリンクします。 – jkaufmann

0
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()); 
     } 
    }); 
関連する問題