Редактировать
Примечание улучшено после ценной информации Клеопатры.
Редактировать2
После полной проверки, лучше всего использовать существующий редактор по умолчанию и настроить это.
Я подумал, что приведу пример с LocalDate
, немного более забавным, чем Integer
. Имеется следующий класс:
class Person(){
...
private ObjectProperty<LocalDate> dueDate;
public void setDueDate(LocalDate value) {
dueDateProperty().set(value);
}
public LocalDate getDueDate() {
return (LocalDate) dueDateProperty().get();
}
public ObjectProperty dueDateProperty() {
if (dueDate == null) dueDate = new SimpleObjectProperty(this, "dueDate");
return dueDate;
}
Затем вы создаете новый класс ячейки редактора, который точно такой же, как TextFieldTreeTableCell
(подкласс TreeTableCell
), который по умолчанию используется для создания редактора для ячейка таблицы TreeTableView
. Однако вы не можете на самом деле создать подкласс TextFieldTreeTableCell
, поскольку, например, его обязательное поле textField
равно private
.
Таким образом, вы полностью копируете код из источника * (всего около 30 строк) и вы называете это
class DueDateEditor extends TreeTableCell<Person, LocalDate> {
...
Затем вам нужно создать новый класс StringConverter
, подклассы LocalDateStringConverter
. Причина подкласса заключается в том, что если вы этого не сделаете, то невозможно поймать DateTimeParseException
, выданный fromString()
при получении недопустимой даты: если вы используете LocalDateStringConverter
, среда JavaFX, к сожалению, перехватывает ее, без каких-либо фреймов в трассировке стека с участием вашего собственного кода. Итак, вы делаете это:
class ValidatingLocalDateStringConverter extends LocalDateStringConverter {
boolean valid;
LocalDate fromString(String value) {
valid = true;
if (value.isBlank()) return null;
try {
return LocalDate.parse(value);
} catch (Exception e) {
valid = false;
}
return null;
}
}
Вернувшись в класс DueDateEditor
, вы затем переписываете метод startEdit
следующим образом. Обратите внимание: как и в случае с классом * 1037, textField
фактически создается лениво при первом редактировании.
@Override
void startEdit() {
if (! isEditable()
|| ! getTreeTableView().isEditable()
|| ! getTableColumn().isEditable()) {
return;
}
super.startEdit();
if (isEditing()) {
if (textField == null) {
textField = CellUtils.createTextField(this, getConverter());
// this code added by me
ValidatingLocalDateStringConverter converter = getConverter();
Callable bindingFunc = new Callable(){
@Override
Object call() throws Exception {
// NB the return value from this is "captured" by the editor
converter.fromString( textField.getText() );
return converter.valid? '' : "-fx-background-color: red;";
}
}
def stringBinding = Bindings.createStringBinding( bindingFunc, textField.textProperty() );
textField.styleProperty().bind( stringBinding );
}
CellUtils.startEdit(this, getConverter(), null, null, textField);
}
}
Примечание: не пытайтесь искать CellUtils
: это частный пакет, рассматриваемый пакет javafx.scene.control.cell.
Чтобы установить вещи до этого вы делаете:
Callback<TreeTableColumn, TreeTableCell> dueDateCellFactory =
new Callback<TreeTableColumn, TreeTableCell>() {
public TreeTableCell call(TreeTableColumn p) {
return new DueDateEditor( new ValidatingLocalDateStringConverter() );
}
}
dueDateColumn.setCellFactory(dueDateCellFactory);
... в результате получается симпатичная, реактивная ячейка редактора: когда содержится недопустимая дата (допустимый шаблон yyyy-mm-dd
; см. другой вариант LocalDate.parse()
для других форматов) фон красный, в остальном нормальный. Ввод с правильной датой работает без проблем. Вы также можете ввести пустое значение String
, которое будет возвращено как null
LocalDate
.
. С учетом вышеизложенного, нажмите Enter с недопустимой датой и установите дату null
. Но переопределить вещи, чтобы предотвратить это (т.е. заставить вас ввести правильную дату или отменить редактирование, например, с помощью Escape), тривиально, используя поле ValidatingLocalDateStringConverter
'valid
:
@Override
void commitEdit( LocalDate newDueDate ){
if( getConverter().valid )
super.commitEdit( newDueDate );
}
* Я не смог найти это онлайн. Я извлек из исходного файла javafx .jar javafx-controls-11.0.2-sources.jar