0

I am trying to develop an JavaFX application to simulate some elevator system.

Each object Elevator is running on its own thread and I want to display each Elevator.toString() in a listview. The problem is that after running the application for a while I will get NullPointerException or IndexOutOfBounds from one, or more, of the elevator threads. I have created a ObservableList of Elevators where I listen for any property changes, then I have another ObservableList of type string that is connected to the listView. The second one is update every time the change listener fires a wasUpdated() from the first list.

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());
                        });
                }
            }
        }
    });

When trying to fix it I have two thoughts, either the ChangeListener fires more changes then the Platform.runLater has time to process or something in the same line as https://stackoverflow.com/a/31414801/9696324. However I cannot get the proposed solutions to work, it usually occurs after 2-3 minutes of running the program without any problems.

When the first error occur the GUI usually freeze (while the program is still running good) and then starts spamming the same errors.

Any thoughts or pointers would be very appreciated, thank you.

The properties are declared in the elevator constructor:

currentFloor = new SimpleIntegerProperty(INITIAL_FLOOR);
    smallSchedule = new SimpleStringProperty("");
    status = new SimpleBooleanProperty(true);
    dir = new SimpleStringProperty("S");
    doors = new SimpleStringProperty("Doors closed");

And the following getters and setter:

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();
    }
}
Cob
  • 3
  • 3
  • What will you be doing with your `ObservableList elevators`? If you’re planning to put it in a ListView or TableView or ComboBox, the right way to do that is to use the original `ObservableList`. – VGR Dec 02 '18 at 06:54
  • Please provide a [mcve] that demonstrates the problem. And stick to naming conventions, in particular fx conventions about properties and getters/setters to their values. f.i. if you expose a property with name _currentFloor_, the property getter should be _currentFloorProperty_ and the value accessors _get/setCurrentFloor_ – kleopatra Dec 02 '18 at 13:49
  • Hey! Thank you for trying to help but I solved it by removing the listener and just update the GUI every 0.1 second, more then enough. I think the problem was that it could not handle that many callbacks from the listener. – Cob Dec 03 '18 at 12:58

0 Answers0