Я пытаюсь разработать приложение JavaFX для имитации некоторой системы лифтов.
Каждый объект Elevator работает в своем собственном потоке, и я хочу отображать каждый Elevator.toString() в виде списка. Проблема в том, что после запуска приложения некоторое время я получаю NullPointerException или IndexOutOfBounds от одного или нескольких потоков лифта. Я создал ObservableList of Elevators, где я прослушиваю любые изменения свойств, затем у меня есть еще один ObservableList строки типа, который подключен к listView. Второй обновляется каждый раз, когда прослушиватель изменений запускает wasUpdated() из первого списка.
final ObservableList<String> elevators = FXCollections.observableArrayList();
final ObservableList<Elevator> obsList = FXCollections.observableArrayList(
new Callback<Elevator, Observable[]>() {
@Override
public Observable[] call(Elevator param) {
return new Observable[]{
param.getCurrentFloorProp(),
param.getDirProp(),
param.getSmallSchedule(),
param.getDoorsProp(),
param.getStatusProp()
};
}
}
);
obsList.addListener(new ListChangeListener<Elevator>() {
@Override
public void onChanged(Change<? extends Elevator> c) {
c.reset();
while (c.next()) {
if (c.wasUpdated()) {
Platform.runLater(() -> {
elevators.set(c.getFrom(), obsList.get(c.getFrom()).toString());
});
}
}
}
});
При попытке исправить это у меня есть две мысли: либо ChangeListener запускает больше изменений, чем Platform.runLater успевает обработать, либо что-то в той же строке, что и https://stackoverflow.com/a/31414801/9696324. Однако я не могу заставить предложенные решения работать, обычно это происходит после 2-3 минут запуска программы без каких-либо проблем.
Когда возникает первая ошибка, графический интерфейс обычно зависает (хотя программа все еще работает хорошо), а затем начинает спамить те же ошибки.
Любые мысли или указатели будут очень признательны, спасибо.
Свойства объявлены в конструкторе лифта:
currentFloor = new SimpleIntegerProperty(INITIAL_FLOOR);
smallSchedule = new SimpleStringProperty("");
status = new SimpleBooleanProperty(true);
dir = new SimpleStringProperty("S");
doors = new SimpleStringProperty("Doors closed");
И следующие геттеры и сеттеры:
public StringProperty getSmallSchedule() {
return smallSchedule;
}
public StringProperty getDoorsProp() {
return doors;
}
public StringProperty getDirProp() {
return dir;
}
public IntegerProperty getCurrentFloorProp() {
return currentFloor;
}
public BooleanProperty getStatusProp() {
return status;
}
public void setCurrentFloor(int floorNr) {
currentFloor.set(floorNr);
}
public void setStatus(boolean status) {
this.status.set(status);
}
public void setDir(char dir) {
this.dir.set(Character.toString(dir));
}
public void setSmallSchedule() {
String temp = "";
for(int i = 0; i < travelSchedule.size()-1;i++) {
if(travelSchedule.get(i)==INT_MAX || i > 2)
break;
temp += " " + travelSchedule.get(i);
}
smallSchedule.set(temp);
}
public void doors(){
try {
Thread.sleep(doorOpen);
doors.set("Doors open");
Thread.sleep(doorWait);
checkMBox();
Thread.sleep(doorClose);
doors.set("Doors closed");
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
ObservableList<String> elevators
? Если вы планируете поместить его в ListView, TableView или ComboBox, правильный способ сделать это — использовать исходныйObservableList<Elevator>
. - person VGR   schedule 02.12.2018