如果滚动到底部太快,JavaFX TableView 会崩溃,自定义单元格也会在操作上变得不合逻辑
Posted
技术标签:
【中文标题】如果滚动到底部太快,JavaFX TableView 会崩溃,自定义单元格也会在操作上变得不合逻辑【英文标题】:JavaFX TableView crashes if scroll to bottom too fast, also custom cell becomes illogical on actions 【发布时间】:2019-03-13 13:19:12 【问题描述】:所以首先我尝试将单元格着色为红色,或者根据同一行的另一列的值将单元格标为红色。 例如,有一个“Enrolled”日期列和一个“DeadlineToEnrollBy”日期列。这是一个通用的例子。
因此,如果截止日期是明天,则单元格不会显示为红色,因为学生还有时间,但如果截止日期是昨天并且学生仍未注册,则“已注册”日期单元格将显示为红色,表示立即关注该学生。我实际上能够做到这一点,但桌子有时表现得“时髦”。
如果我快速滚动到底部,我会收到错误消息。有时上下滚动时,红色单元格会在其他位置,或者列中的所有单元格都会变成红色,即使它不应该是红色。我相信即使上传新数据,因此刷新表格也会导致红色单元格熄灭。
我得到的错误是
Exception in thread "JavaFX Application Thread"
java.lang.IndexOutOfBoundsException
在这行代码
Person student= ClassPanelView.retrieveTable().getItems.get(getIndex());
这是相关的代码流
在类面板视图中
createTable()
.
.
TableColumn<Person, Date> enrolledBy = new TableColumn<>("Enrolled");
enrolledBy.setCellValueFactory(new PropertyValueFactory<>("dateEnrolled"));
enrolledBy.setCellFactory(column ->
return new util.EditEnrolledDateCell<Person, Date>();
);
table.getColumns().addAll(enrolledBy, ..etc);
public static TableView<Person> retrieveTable()
return table;
列调用/返回的其他类/单元格
public class EditEnrolledDateCell<S,T> extends TextFieldTableCell<Person, Date>
private Date now = new Date();
...
...
@Override
public void updateItem(Date item, boolean empty)
super.updateItem(item, empty);
if (item == null || empty)
if(this.getIndex() > -1)
/*int currentIndex = indexProperty().getValue() < 0 ? 0
: indexProperty().getValue(); */
Person student = ClassPanelView.retrieveTable().getItems().get(getIndex()); //<==== This line is the problem
if(student.getDeadline != null && student.getDeadline.before(now))
setStyle("-fx-border-color: #f40404;\n"
+ "-fx-border-width: 1 1 1 1;\n");
else //if there is something here, format it
setStyle("");
setText(GuiUtils.monthFirstDateFormat.format(item));
任何提示/知识将不胜感激!谢谢
编辑:
【问题讨论】:
【参考方案1】:您永远不会为未超过截止日期的人重置单元格的样式。您需要进行此类更新。此外,表格末尾可能存在具有非负索引的空单元格。 (只有当单元格为空时,您才尝试检索此人。)
另外,为了使单元格更易于重复使用,我建议使用 TableCell.getTableView
而不是访问 static
字段。
@Override
public void updateItem(Date item, boolean empty)
super.updateItem(item, empty);
if (empty)
setStyle(null);
setText("");
else
Person student = getTableView().getItems().get(getIndex());
setStyle(student.getDeadline != null && !now.after(student.getDeadline)
? null
: "-fx-border-color: #f40404; -fx-border-width: 1 1 1 1;");
// I recommend passing the formatter in a constructor to make the cell type easier to reuse
setText(item == null ? "" : GuiUtils.monthFirstDateFormat.format(item));
注意:您还应该将字段 getDeadline
重命名为 deadline
。 getDeadline
按照惯例是 deadline
属性的 getter 方法的名称,我想不出以通常用于 getter 的方式命名字段的原因。
此外,我目前还没有看到将类型参数添加到自定义单元格类型的理由。这些类型从未使用过。
public class EditEnrolledDateCell extends TextFieldTableCell<Person, Date>
在某些情况下,您可能希望保留这些。如果您想使用带有TableView<T>
的单元格,其中T
是Person
的子类型,或者在列中使用作为Date
子类型的值类型,但这需要不同的声明:
public class EditEnrolledDateCell<S extends Person, T extends Date> extends TextFieldTableCell<S, T>
...
@Override
public void updateItem(T item, boolean empty)
...
此外,如果可能,我建议使用LocalDate
而不是Date
,因为这种类型更现代/更易于使用。
【讨论】:
感谢 F***,您能详细说明这种类型的实现吗?我的要求是空白单元格为红色(如果已通过截止日期),而不是您当前的实现,它为已经有日期的单元格着色。这是我不想要的相反效果。但是你指出,一定是这种更新。如果 item 为 null,那么我不能自定义单元格?我试过了,但刚才失败了。我很抱歉没有完全理解 @E.C 在这种情况下,尽可能靠近您的代码。更新了我的示例以设置截止日期在now
之后的所有非空单元格。此外,它不会使用enrolledDate
或null
设置单元格样式。这是期望的行为吗?
你的回答太棒了,我不再有错误,但我想要的行为与为空/空“注册日期”单元格着色有关。请参阅上面的编辑。以上是关于如果滚动到底部太快,JavaFX TableView 会崩溃,自定义单元格也会在操作上变得不合逻辑的主要内容,如果未能解决你的问题,请参考以下文章
JavaFx 13 - TableView 垂直滚动条处理程序返回 NullPointerException