Прежде всего мои объекты:JavaFX ConcurrentModificationException withouth (сознательно) implemtented темы
public class Group {
private final ObservableList<IDevice> sourceList;
private final ObservableList<IDevice> destinationList;
private final ObservableList<Mapping> mappingList;
...}
public class Mapping {
private final IDevice source;
private final IDevice destination;
private final MappingMode mode;
public final StringProperty sourceName = new SimpleStringProperty();
public final StringProperty destinationName = new SimpleStringProperty();
public final StringProperty modeName = new SimpleStringProperty();
...}
В основном группа содержит два списка мобильным iУстройством, которые могут быть либо источника или назначения и список отображения, который содержит один из них и один двух режимов (перечисление).
Списки IDevice отображаются в собственном представлении списка с таблицей между ними, представляющей сопоставление (содержащий один столбец из первого, один из второго списка и столбец режима).
Я добавил их через setItems, это CellFactory для ListViews
private Callback<ListView<IDevice>, ListCell<IDevice>> getFullNameDisplay() {
return new Callback<ListView<IDevice>, ListCell<IDevice>>() {
@Override
public ListCell<IDevice> call(ListView<IDevice> p) {
ListCell<IDevice> cell = new ListCell<IDevice>() {
@Override
protected void updateItem(IDevice t, boolean bln) {
super.updateItem(t, bln);
if (t != null) {
setText(t.getFullName());
}
else
setText("");
}
};
return cell;
}
};
}
Колонки устанавливаются следующим образом:
sourceColumn.setCellValueFactory(cellData -> cellData.getValue().sourceName);
destinationColumn.setCellValueFactory(cellData -> cellData.getValue().destinationName);
modeColumn.setCellValueFactory(cellData -> cellData.getValue().modeName);
я добавил две кнопки для каждого ListView для добавления и удаления новые предметы.
Конечно, если удалить источник или устройство назначения, я хочу, чтобы все его отображений удалены, так что я добавил ListChangeListener в двух списках:
private ListChangeListener<IDevice> getDeviceChangeListener() {
return (javafx.collections.ListChangeListener.Change<? extends IDevice> c) -> {
while (c.next()) {
if (c.wasRemoved()) {
c.getRemoved().stream().forEach((d) -> {
mappingList.stream().filter((map) -> (map.getSource().equals(d) || map.getDestination().equals(d))).forEach((map) -> {
mappingList.remove(map);
});
});
}
}
};
}
Это также делает то, что я намеревался это сделать (и все рефакторинги, которые я пытался сделать), но я не могу понять, почему это вызывает (большую часть времени) ConcurrentModificationException, поскольку я еще не использовал потоковую передачу в своем приложении. Кажется, что он не запускается каждый раз, что я понимаю, может быть, повезло в планировании, если бы я использовал потоки. Результат правильный, хотя
Кто-нибудь подскажет?
Заранее спасибо
'ConcurrentModificationException' не имеет ничего общего с многопоточностью: это просто означает, что вы изменили содержание списка, пока вы итерацию через него (что смущает итератор). –