重构文件类型相关Service以支持国际化查询 添加findOneByLang辅助方法统一查询逻辑 实现StringConverter支持UI控件显示 优化缓存配置和查询性能 新增UnitStringConverter和CustomerCatalogStringConverter 完善文档和测试用例
6.4 KiB
6.4 KiB
TableCell 实现规则与模式指南
1. 目的与作用
TableCell 是 JavaFX TableView 组件中的关键元素,负责表格中单个单元格的渲染和交互。在 Contract-Manager 项目中,TableCell 主要用于:
- 显示各种类型的数据(数字、日期、实体引用等)
- 提供自定义的显示格式和样式
- 支持异步加载关联数据
- 实现单元格内编辑功能
2. 文件结构与命名规范
- 文件位置:
client/src/main/java/com/ecep/contract/controller/table/cell/ - 命名规范:使用 PascalCase(驼峰命名法,首字母大写),以
TableCell结尾- 示例:
CompanyTableCell.java、LocalDateFieldTableCell.java
- 示例:
3. TableCell 分类与实现模式
3.1 基础 TableCell
直接继承 JavaFX 的 TableCell 类,适用于简单的数据显示。
实现规则:
- 继承
TableCell<S, T>,其中 S 是表格行数据类型,T 是单元格数据类型 - 实现
updateItem(T item, boolean empty)方法 - 提供静态的
forTableColumn()工厂方法
示例:
public class NumberTableCell<S> extends TableCell<S, Number> {
private final NumberStringConverter numberStringConverter;
public NumberTableCell(NumberStringConverter numberStringConverter) {
this.numberStringConverter = numberStringConverter;
}
@Override
protected void updateItem(Number item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
} else {
setText(numberStringConverter.toString(item));
}
}
public static <S> Callback<TableColumn<S, Number>, TableCell<S, Number>> forTableColumn(NumberStringConverter numberStringConverter) {
return param -> new NumberTableCell<>(numberStringConverter);
}
}
3.2 异步更新 TableCell
继承 AsyncUpdateTableCell,用于异步加载并显示关联的实体数据。
实现规则:
- 继承
AsyncUpdateTableCell<V, K, T>,其中 V 是表格行数据类型,K 是 ID 类型,T 是实体类型 - 提供构造函数接收服务对象,或实现
getServiceBean()方法从 Spring 容器获取服务 - 可选:重写
initialize()方法自定义实体加载逻辑 - 可选:重写
format()方法自定义实体显示格式
示例:
@NoArgsConstructor
public class CompanyTableCell<V> extends AsyncUpdateTableCell<V, Integer, CompanyVo> {
public CompanyTableCell(CompanyService companyService) {
setService(companyService);
}
@Override
protected CompanyService getServiceBean() {
return SpringApp.getBean(CompanyService.class);
}
}
3.3 可编辑 TableCell
实现单元格内编辑功能,如日期选择、文本编辑等。
实现规则:
- 继承
TableCell或其子类 - 实现
startEdit()、cancelEdit()方法 - 在
updateItem()方法中处理编辑状态的显示 - 提供编辑控件和事件处理
示例:
public class LocalDateFieldTableCell<S> extends TableCell<S, LocalDate> {
private final DatePicker datePicker;
// 构造函数、converter 属性等
@Override
public void startEdit() {
if (isEmpty()) {
return;
}
super.startEdit();
setGraphic(datePicker);
datePicker.setConverter(getConverter());
datePicker.setValue(getItem());
datePicker.requestFocus();
}
@Override
public void cancelEdit() {
super.cancelEdit();
LocalDate item = getItem();
if (item == null) {
setText(null);
} else {
setText(getConverter().toString(item));
}
setGraphic(null);
}
@Override
protected void updateItem(LocalDate item, boolean empty) {
// 实现更新逻辑
}
}
4. AsyncUpdateTableCell 核心功能
AsyncUpdateTableCell 是项目中最常用的基类,提供以下核心功能:
4.1 异步加载机制
- 显示占位符(
#id)直到数据加载完成 - 使用线程池执行异步任务
- 自动取消不再需要的异步任务
- 确保在 JavaFX 应用线程更新 UI
4.2 实体显示格式化
- 默认使用
toString()方法格式化实体 - 对
NamedEntity和BasedEntity有特殊处理 - 允许子类重写
format()方法自定义格式
4.3 服务获取方式
- 通过构造函数注入服务
- 或通过
getServiceBean()方法从 Spring 容器获取
5. 特殊情况处理
5.1 非 Integer 类型 ID
当实体 ID 不是 Integer 类型时,需要重写 initialize() 方法:
@Override
protected ContractFileTypeLocalVo initialize() {
ContractFileType item = getItem();
ContractFileTypeLocalVo localVo = getServiceBean().findByType(
Desktop.instance.getActiveEmployee().localeProperty().get(), item);
return localVo;
}
5.2 自定义显示格式
当需要自定义实体的显示格式时,重写 format() 方法:
@Override
public String format(ContractFileTypeLocalVo entity) {
if (entity == null) {
return null;
}
return entity.getValue();
}
6. 工厂方法模式
所有 TableCell 类都应提供静态的 forTableColumn() 工厂方法,用于创建单元格工厂回调:
- 无参数版本:
public static <S> Callback<TableColumn<S, T>, TableCell<S, T>> forTableColumn() - 带服务参数版本:
public static <S> Callback<TableColumn<S, T>, TableCell<S, T>> forTableColumn(ServiceType service)
7. 代码规范
- 使用 Lombok 注解(如
@NoArgsConstructor)简化代码 - 添加适当的 JavaDoc 注释
- 遵循 JavaFX 最佳实践
- 处理空值和异常情况
- 确保线程安全,UI 更新在 JavaFX 应用线程执行
8. 实现检查清单
创建新的 TableCell 时,请检查以下项目:
- 类名符合
*TableCell命名规范 - 放置在正确的包路径下
- 选择合适的基类(TableCell、AsyncUpdateTableCell)
- 实现必要的构造函数
- 实现或重写
updateItem()方法 - 提供静态的
forTableColumn()工厂方法 - 对于异步更新类型,实现
getServiceBean()或提供服务注入 - 添加适当的注释
- 处理空值和异常情况
9. 示例实现
9.1 简单数据类型 TableCell
参考 NumberTableCell.java、LocalDateFieldTableCell.java
9.2 实体引用 TableCell
参考 CompanyTableCell.java、ContractTableCell.java
9.3 特殊处理 TableCell
参考 ContractFileTypeTableCell.java