Не обновляется отображение 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 шт):
В методе Presenter.Components.TasksList.TasksListController.TaskCard#updateItem вместо простого переноса значения
this.titleLabel.setText(observableTask.getTitle().getValue())
используйте связывание:
titleLabel.textProperty().bind(observableTask.getTitle())
Тогда при обновлении ObservableTask#title будет обновляться и карточка. Аналогичное связывание нужно сделать и для ObservableTask#note.
