JavaFX TableView аварийно завершает работу, если прокрутка вниз слишком быстрая, и пользовательская ячейка становится нелогичной при выполнении - PullRequest
0 голосов
/ 13 марта 2019

Итак, сначала я пытаюсь закрасить ячейку красным, или обвести ячейку красным, основываясь на значении другого столбца, той же строки.Например, есть столбец «Дата регистрации» и столбец «Дата 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;
}

Другой класс / Ячейка, которую вызывает / возвращает столбец

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

1 Ответ

0 голосов
/ 13 марта 2019

Вы никогда не сбрасываете стиль ячейки для людей, не превышающих установленный срок. Вам нужно сделать такое обновление. Кроме того, в конце таблицы могут быть пустые ячейки с неотрицательным индексом. (Вы пытаетесь получить человека, только если ячейка пуста.)

Также, чтобы сделать ячейку более пригодной для повторного использования, я рекомендую использовать 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, и я не могу придумать причину, по которой именование поля способом, который вы обычно используете для получения, было бы хорошей практикой.

Кроме того, в настоящее время я не вижу причин для добавления параметров типа в пользовательский тип ячейки. Эти типы никогда не используются.

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, если это возможно, так как этот тип более современный / более простой в использовании.

...