表格编辑和渲染器
默认情况下单元格不可编辑,开启步骤如下:
首先,调用方法设置表格为可编辑的:
tableView.setEditable(true);
其次,设置可编辑列的单元格渲染器,JavaFX有4个内置的单元渲染器:
TextFieldTableCell用于启用使用TextField编辑单元格值。
CheckBoxTableCell用于启用使用CheckBox编辑单元格值。
ChoiceBoxTableCell用于启用使用ChoiceBox编辑单元格值。
ComboBoxTableCell用于启用使用ComboBox编辑单元格值。
使用方法示例:
column1.setCellFactory(TextFieldTableCell.forTableColumn());
失去焦点自动提交
内置TextFieldTableCell在编辑后必须回车才能提交保存。如果需要理解编辑框焦点自动提交保存,可使用自定义的渲染器,示例如下:
// 设置渲染器
column2.setCellFactory((tableColumn) -> new EditingCell<Person>());
/**
* 失去焦点自动提交
*
* @author Raygo
* @since 2022年3月3日
* @param <T>
*/
public class EditingCell<T> extends TableCell<T, String> {
private TextField textField;
public EditingCell() {
}
@Override
public void startEdit() {
if (!isEmpty()) {
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}
}
@Override
public void commitEdit(String newValue) {
if (!isEditing() && !newValue.equals(this.getItem())) {
TableView<T> table = this.getTableView();
if (this.getTableView() != null) {
TableColumn<T, String> col = this.getTableColumn();
CellEditEvent<T, String> event = new CellEditEvent<T, String>(table,
new TablePosition<T, String>(table, this.getIndex(), col), TableColumn.editCommitEvent(),
newValue);
Event.fireEvent(col, event);
}
}
super.commitEdit(newValue);
updateItem(newValue, false);
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textField.focusedProperty().addListener((ob, old, now) -> {
if (!now) {
commitEdit(textField.getText());
}
});
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}
嵌套列
TableView支持列的嵌套,例如:一个名为“地址”的表列可以细分为两个子列:“国家”和“城市”,效果如下图:
代码示例:
// 嵌套列
TableColumn<Person, String> address = new TableColumn<>("地址");
TableColumn<Person, String> country = new TableColumn<>("国家");
TableColumn<Person, String> city = new TableColumn<>("城市");
// 把子列添加到父列
address.getColumns().addAll(country, city);
// 设置子列的渲染器,父列不需要设置
country.setCellValueFactory(new PropertyValueFactory<>("country"));
city.setCellValueFactory(new PropertyValueFactory<>("city"));
// 添加列到表格视图
tableView.getColumns().add(address);