JavaFX2:在TableCell中保存编辑
在我的JavaFX程序中,我使用一个TableCell,您可以在其中编辑一个值。如JavaFX页面上的示例所示,我使用此函数保存更改(函数设置在编辑单元的TextField上)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){ 取消编辑();
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已更改(observeValueimport 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());
}
});