Не обновляется отображение ListCell при обновлении элемента ObservableList в JavaFX

В рамках упражнения "TODO List" создаю такой редактируемых карточек:

введите сюда описание изображения

На данный момент до создания новых тасков пока не дошёл, но уже реализовал перенос данных в поля ввода при клике на карточку. Метод сохранения обновленного таска тоже реализовал, но список не обновляется.

public class TaskEditorController {

  private static TaskEditorController selfSoleInstance;

  @FXML private TextField taskTitleTextField;
  @FXML private TextArea taskNoteTextArea;
  @FXML private Button saveChangesButton;

  private ObservableTask targetTask;


  public static TaskEditorController getInstance() {
    return TaskEditorController.selfSoleInstance;
  }

  @FXML
  private void initialize() {
    TaskEditorController.selfSoleInstance = this;
  }


  public void beginTaskEditing(ObservableTask targetTask) {
    this.targetTask = targetTask;
    this.taskTitleTextField.setText(targetTask.getTitle().getValue());
    this.taskNoteTextArea.setText(targetTask.getNote().getValue());
  }

  @FXML
  public void saveEditedTask() {

    this.targetTask.setTitle(this.taskTitleTextField.getText());
    this.targetTask.setNote(this.taskNoteTextArea.getText());

    // Тут всё нормально - проверил что новые данные подбираются.
    System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    System.out.println(this.taskTitleTextField.getText());
    System.out.println(this.taskNoteTextArea.getText());
  }
}

Инициализация коллекции тасков происходит следующим образом:

public class TasksListController {

  
  /* --- Data ------------------------------------------------------------------------------------------------------- */
  private static TasksGateway tasksGateway;


  /* --- GUI Elements ----------------------------------------------------------------------------------------------- */
  @FXML private ListView<ObservableTask> tasksListView;


  @FXML
  private void initialize() {

    ObservableList<ObservableTask> observableTasks = FXCollections.observableArrayList();

    for (Map.Entry<String, Task> pair: TasksListController.tasksGateway.getAll().entrySet()) {
      observableTasks.add(new ObservableTask(pair.getValue()));
    }

    this.tasksListView.setCellFactory(list -> new TaskCard());
    this.tasksListView.setItems(observableTasks);

    this.tasksListView.getSelectionModel().selectedItemProperty().addListener(
        (observable, oldValue, newValue)-> this.onSelectTask(newValue)
    );
  }


  private void onSelectTask(ObservableTask targetTask) {
    TaskEditorController.getInstance().beginTaskEditing(targetTask);
  }
}

Что я упустил?

? Репозиторий приложения

Дополнительно: об обмене данными с формой ввода

Это не по теме, но если Вам не понравилась строка TaskEditorController.getInstance().beginTaskEditing(targetTask);, то я её объясню.

На данный момент я не знаю, как в JavaFX организован обмен данными между компонентами произвольного взаимного расположения. Из веб-разработки я знаю, что в таких фреймворках, как Vue, обмен данными может осуществляться посредством:

  • Свойств компонента (им может быть и функция)
  • Генераторов (эмиттеров) событий
  • Продвинутый вариант - единая шина событий типа Vuex

Как обычно делают в JavaFX - мне пока неизвестно, но я попробовал получить инстанс контроллера формы ввода через статический метод getInstance. Перенос данных в форму работает, но является ли это причиной возникшей проблемы - не знаю.


Ответы (1 шт):

Автор решения: Dmitry Terentjev

В методе Presenter.Components.TasksList.TasksListController.TaskCard#updateItem вместо простого переноса значения

this.titleLabel.setText(observableTask.getTitle().getValue())

используйте связывание:

titleLabel.textProperty().bind(observableTask.getTitle())

Тогда при обновлении ObservableTask#title будет обновляться и карточка. Аналогичное связывание нужно сделать и для ObservableTask#note.

→ Ссылка