-
-
Save opensourcelib/6d9446787322397d993debe9682bc513 to your computer and use it in GitHub Desktop.
TextAreaTableCell, see Stack Overflow question: http://stackoverflow.com/questions/27666382/editable-multiline-cell-in-tableview
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javafx.beans.binding.Bindings; | |
import javafx.beans.property.ObjectProperty; | |
import javafx.beans.property.SimpleObjectProperty; | |
import javafx.scene.control.Cell; | |
import javafx.scene.control.TableCell; | |
import javafx.scene.control.TableColumn; | |
import javafx.scene.control.TextArea; | |
import javafx.scene.input.KeyCode; | |
import javafx.util.Callback; | |
import javafx.util.StringConverter; | |
import javafx.util.converter.DefaultStringConverter; | |
public class TextAreaTableCell<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 list -> new TextAreaTableCell<>(converter); | |
} | |
private static <T> String getItemText(Cell<T> cell, StringConverter<T> converter) { | |
return converter == null ? cell.getItem() == null ? "" : cell.getItem() | |
.toString() : converter.toString(cell.getItem()); | |
} | |
private static <T> TextArea createTextArea(final Cell<T> cell, final StringConverter<T> converter) { | |
TextArea textArea = new TextArea(getItemText(cell, converter)); | |
textArea.setOnKeyReleased(t -> { | |
if (t.getCode() == KeyCode.ESCAPE) { | |
cell.cancelEdit(); | |
t.consume(); | |
} | |
else if(t.getCode() == KeyCode.ENTER && t.isShiftDown()) { | |
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(textArea.getText())); | |
t.consume(); | |
} | |
}); | |
textArea.prefRowCountProperty().bind(Bindings.size(textArea.getParagraphs())); | |
return textArea; | |
} | |
private void startEdit(final Cell<T> cell, final StringConverter<T> converter) { | |
textArea.setText(getItemText(cell, converter)); | |
cell.setText(null); | |
cell.setGraphic(textArea); | |
textArea.selectAll(); | |
textArea.requestFocus(); | |
} | |
private static <T> void cancelEdit(Cell<T> cell, final StringConverter<T> converter) { | |
cell.setText(getItemText(cell, converter)); | |
cell.setGraphic(null); | |
} | |
private void updateItem(final Cell<T> cell, final StringConverter<T> converter) { | |
if (cell.isEmpty()) { | |
cell.setText(null); | |
cell.setGraphic(null); | |
} else { | |
if (cell.isEditing()) { | |
if (textArea != null) { | |
textArea.setText(getItemText(cell, converter)); | |
} | |
cell.setText(null); | |
cell.setGraphic(textArea); | |
} else { | |
cell.setText(getItemText(cell, converter)); | |
cell.setGraphic(null); | |
} | |
} | |
} | |
private TextArea textArea; | |
private ObjectProperty<StringConverter<T>> converter = new SimpleObjectProperty<>(this, "converter"); | |
public TextAreaTableCell() { | |
this(null); | |
} | |
public TextAreaTableCell(StringConverter<T> converter) { | |
this.getStyleClass().add("text-area-table-cell"); | |
setConverter(converter); | |
} | |
public final ObjectProperty<StringConverter<T>> converterProperty() { | |
return converter; | |
} | |
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()) { | |
if (textArea == null) { | |
textArea = createTextArea(this, getConverter()); | |
} | |
startEdit(this, getConverter()); | |
} | |
} | |
@Override | |
public void cancelEdit() { | |
super.cancelEdit(); | |
cancelEdit(this, getConverter()); | |
} | |
@Override | |
public void updateItem(T item, boolean empty) { | |
super.updateItem(item, empty); | |
updateItem(this, getConverter()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
StackOverFlow Question
Ok, the basic idea is to copy the TextFieldTableColumn and adjust its behavior to create a TextAreaTableColumn. I hacked a small working example implementation together: https://gist.github.com/eckig/30abf0d7d51b7756c2e7
Usage:
TableColumn column = new TableColumn<>();
column.setCellValueFactory(...);
column.setCellFactory(TextAreaTableCell.forTableColumn()); // add StringConverter if neccessary
tableView.getColumns().add(column);
Adjust prefRowCount to show only the necessary amount of rows.
Maybe adjust prefColumnCount?
But hopefully you get the idea ;-)
Commit is now done by Shift+Enter. On focus lost is not a good idea, so I discarded it. Additionally I found a solution for the row count property. It is not working 100% perfect, but it is a good start for now. – eckig Dec 28 '14 at 9:27