如果滚动到底部太快,JavaFX TableView崩溃,自定义单元格在操作上变得不合逻辑

问题描述 投票:0回答:1

首先,我尝试将单元格着色为红色,或者根据另一列的值,同一行将单元格用红色勾勒出来。例如,有一个“已注册”日期列和一个“DeadlineToEnrollBy”日期列。这是一个通用的例子。

因此,如果截止日期是明天,则单元格将不会显示红色,因为学生仍有时间,但如果截止日期是昨天且学生仍未注册,则“已注册”日期单元格将显示为红色,表示立即关注那个学生。我实际上能够做到这一点,但桌子有时表现“时髦”。

如果我快速滚动到底部,我会收到错误。有时向上和向下滚动时,红色单元格将位于其他位置,或者列中的所有单元格都将为红色,即使它不应该是红色。我相信即使上传新数据,因此刷新表也会导致红色单元关闭。

我得到的错误是

 Exception in thread "JavaFX Application Thread"
 java.lang.IndexOutOfBoundsException

在这行代码上

Person student= ClassPanelView.retrieveTable().getItems.get(getIndex());

以下是相关的代码流

在ClassPanelView中

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;
}

列调用/返回的另一个类/ Cell

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));
        }
    }

}

任何提示/知识将不胜感激!谢谢

编辑:Desired Behavior

uitableview javafx tableview indexoutofboundsexception
1个回答
0
投票

对于没有超过截止日期的人,您永远不会重置单元格的样式。您需要进行此类更新。此外,在表的末尾可能存在具有非负索引的空单元格。 (您只有在单元格为空时才尝试检索此人。)

为了使细胞更可重复使用,我建议使用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。按照惯例,getDeadlinedeadline属性的getter方法的名称,我想不出以一种你通常用于getter的方式命名一个字段的原因是一个好习惯。

此外,我目前没有看到将类型参数添加到自定义单元格类型的原因。这些类型从未使用过。

public class EditEnrolledDateCell extends TextFieldTableCell<Person, Date>

可能存在您想要保留这些的情况。如果你想使用带有TableView<T>的单元格,其中TPerson的子类型,或者在Date的子类型列中使用值类型,但这需要不同的声明:

public class EditEnrolledDateCell<S extends Person, T extends Date> extends TextFieldTableCell<S, T> {

     ...

    @Override
    public void updateItem(T item, boolean empty) {
...

此外,如果可能的话,我建议使用LocalDate而不是Date,因为这种类型更现代/更容易使用。

© www.soinside.com 2019 - 2024. All rights reserved.