Der einfachste Weg, dies zu tun, ist mit einer Bindungsbibliothek von Drittanbietern: ReactFX 2.0 hat diese Funktionalität eingebaut, wie beschrieben here. Mit, dass Sie
TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
lastNameColumn.setEditable(true);
lastNameColumn.setCellFactory(tc -> {
TableCell<Person, String> cell = new TextFieldTableCell<>();
cell.editableProperty().bind(
// horrible cast needed because TableCell.tableRowProperty inexplicably returns a raw type:
Val.flatMap(cell.tableRowProperty(), row -> (ObservableValue<Person>)row.itemProperty())
.flatMap(Person::newRecordProperty)
.orElseConst(false));
return cell ;
});
tun können (nimmt ein Person
Tabelle Modellobjekt mit den offensichtlichen JavaFX Eigenschaften und Methoden).
Ohne die Bibliothek, müssen Sie eine ziemlich miserable verschachtelte Liste der Zuhörer:
TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
lastNameColumn.setEditable(true);
lastNameColumn.setCellFactory(tc -> {
TableCell<Person, String> cell = new TextFieldTableCell<>();
ChangeListener<Boolean> newRecordListener = (obs, wasNewRecord, isNewRecord) -> updateEditability(cell);
ChangeListener<Person> rowItemListener = (obs, oldPerson, newPerson) -> {
if (oldPerson != null) {
oldPerson.newRecordProperty().removeListener(newRecordListener);
}
if (newPerson != null) {
newPerson.newRecordProperty().addListener(newRecordListener);
}
updateEditability(cell);
};
ChangeListener<TableRow> rowListener = (obs, oldRow, newRow) -> {
if (oldRow != null) {
((ObservableValue<Person>)oldRow.itemProperty()).removeListener(rowItemListener);
if (oldRow.getItem() != null) {
((Person)oldRow.getItem()).newRecordProperty().removeListener(newRecordListener);
}
}
if (newRow != null) {
((ObservableValue<Person>)newRow.itemProperty()).addListener(rowItemListener);
if (newRow.getItem() != null) {
((Person)newRow.getItem()).newRecordProperty().addListener(newRecordListener);
}
}
updateEditability(cell);
};
cell.tableRowProperty().addListener(rowListener);
return cell ;
});
und dann
private void updateEditability(TableCell<Person, String> cell) {
if (cell.getTableRow() == null) {
cell.setEditable(false);
} else {
TableRow<Person> row = (TableRow<Person>) cell.getTableRow();
if (row.getItem() == null) {
cell.setEditable(false);
} else {
cell.setEditable(row.getItem().isNewRecord());
}
}
}
Eine Alternative eines "legacy Stil" API ist mit
TableColumn<Person, String> lastNameColumn = new TableColumn<>("Last Name");
lastNameColumn.setEditable(true);
lastNameColumn.setCellFactory(tc -> {
TableCell<Person, String> cell = new TextFieldTableCell<>();
cell.editableProperty().bind(
Bindings.selectBoolean(cell.tableRowProperty(), "item", "newRecord"));
return cell ;
});
Ich mag diese Option nicht, weil es keine Art Sicherheit (oder überhaupt Compiler-Checks) und Werbung fehlt Zusätzlich würde in einigen früheren Versionen von JavaFX fast endlose Warnmeldungen erzeugt werden, wenn eine der Eigenschaften in der "Kette" Nullwerte hätte (was in diesem Fall häufig der Fall ist). Ich glaube, das letztere Problem ist behoben, aber die ReactFX-Version von diesem ist viel besser, imho.
Sowohl 'TableColumn' als auch' TableCell' haben einen bearbeitbaren Zustand. Machen Sie die Spalte editierbar und verwenden Sie eine Zellenfactory, die den bearbeitbaren Zustand der Zelle aktualisiert. Wenn 'NewRecord' unveränderlich ist, können Sie dies einfach und direkt in der 'updateItem'-Methode tun; Wenn es veränderlich ist, dann brauchen Sie ein wenig Trickserei mit Zuhörern, um den 'newRecord'-Zustand richtig zu beobachten. –
Ich habe versucht, das von der CellFactory zu tun - aber ich war nicht in der Lage, genau zu bestimmen, wie man das von dort herausfinden kann? Können Sie ein Snippet bereitstellen? Das könnte alles sein, was ich brauche. Vielen Dank. –
Ist 'newRecord' veränderbar oder nicht? –