JavaFX自定义DatePicker TableCell筛选表格时日期显示错位问题
JavaFX TableView筛选后DatePicker单元格内容错位问题
问题表现
为单元格选择日期时功能正常:
触发FilteredList筛选谓词过滤后,已选日期错位显示到表格底部,恢复筛选规则后日期回到正确位置:
问题原因
- 核心原因是自定义
DatePickerTableCell未重写updateItem()方法。JavaFX的TableCell采用复用机制,列表筛选、排序、滚动导致视图变化时,单元格会被重用来绑定不同行的数据,原有逻辑只在编辑提交、取消编辑时更新显示内容,没有在单元格复用时重置状态,导致旧内容残留错位。 - 实体类
SetterGetter未遵循JavaFX属性绑定规范,日期属性未正确初始化、缺少标准属性访问器,编辑提交的值没有持久化到实体的可观察属性中,列表刷新时单元格无法获取正确的绑定值。 - 原有
commitEdit()逻辑中手动调用setItem()属于错误操作,该方法由框架内部管理单元格状态,手动调用会打乱单元格的生命周期状态。
修复方案
- 为
DatePickerTableCell重写updateItem()方法,统一处理空单元格、编辑状态、非编辑状态的显示逻辑,确保单元格复用时能根据当前绑定的数据正确更新内容。 - 修正
SetterGetter实体类,按照JavaFX Bean规范实现日期属性的访问器,初始化属性避免空指针,确保编辑值能正确写入实体。 - 移除错误的手动
setItem()调用,调整列的CellValueFactory绑定到正确的属性对象,修正初始化、新增行的传参逻辑。
修正后的DatePickerTableCell代码
import javafx.event.ActionEvent; import javafx.scene.control.DatePicker; import javafx.scene.control.TableCell; import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class DatePickerTableCell extends TableCell<SetterGetter, LocalDate> { private final DatePicker datePicker = new DatePicker(); private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); public DatePickerTableCell() { datePicker.setOnAction((ActionEvent event) -> commitEdit(datePicker.getValue())); } @Override protected void updateItem(LocalDate item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { setText(null); setGraphic(null); return; } if (!isEditing()) { setText(item.format(DATE_FORMATTER)); setGraphic(null); } else { datePicker.setValue(item); setText(null); setGraphic(datePicker); } } @Override public void startEdit() { super.startEdit(); datePicker.setValue(getItem()); setText(null); setGraphic(datePicker); datePicker.requestFocus(); } @Override public void cancelEdit() { super.cancelEdit(); setText(getItem() == null ? null : getItem().format(DATE_FORMATTER)); setGraphic(null); } @Override public void commitEdit(LocalDate newValue) { super.commitEdit(newValue); SetterGetter rowData = getTableView().getItems().get(getIndex()); rowData.setDate(newValue); setText(newValue == null ? null : newValue.format(DATE_FORMATTER)); setGraphic(null); } }
修正后的SetterGetter实体类代码
import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import java.time.LocalDate; public class SetterGetter { private int id; private String name; private final ObjectProperty<LocalDate> date; private int status; public SetterGetter(int id, String name, LocalDate date, int status) { this.id = id; this.name = name; this.date = new SimpleObjectProperty<>(date); this.status = status; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public ObjectProperty<LocalDate> dateProperty() { return date; } public LocalDate getDate() { return date.get(); } public void setDate(LocalDate date) { this.date.set(date); } }
Controller类需要调整的代码片段
// 修正日期列的绑定,绑定到属性对象 colDueDate.setCellValueFactory(b -> b.getValue().dateProperty()); // 修正初始化数据的传参 mainTaskList.addAll( new SetterGetter(0, null, (LocalDate) null, 1), new SetterGetter(1, null, (LocalDate) null, 1) ); // 修正新增行方法的传参 @FXML void addCheck(ActionEvent event) { mainTaskList.add(new SetterGetter(0, null, (LocalDate) null, 0) ); }
其余原有主启动类、FXML布局代码不需要修改,调整后筛选、编辑、新增操作都不会再出现内容错位问题。
内容的提问来源于stack exchange,提问作者احمد ربايعة
相关产品推荐
相关产品推荐

