Метод initialize
вызывается FXMLLoader
во время вызова load
. В то время ни одно из свойств не было установлено, поскольку вы «предварительно загружаете» сцену.
Я настоятельно рекомендую не использовать данные static
для передачи информации. Конечно, удобно иметь доступ к данным, но это происходит за счет отсутствия контроля над тем, когда и каким кодом изменяются значения, и невозможности иметь более одного судна одновременно.
Вместо этого вы можете использовать свойства javafx для решения этой проблемы. В следующем дизайне класса просто отсутствует пропущенные правильные модификаторы видимости, сеттеры, геттеры (свойства), инициализации и конструкторы, но я уверен, что вы можете добавить это самостоятельно:
class Starship
StringProperty name;
ObjectProperty<CrewMember> captain;
// possibly replace the following property with individual properties for roles
// or use a ObservableMap<Role, CrewMember> instead???
ObservableList<CrewMember> crew;
}
// could we make this immutable instead???
class CrewMember {
StringProperty name;
ObjectProperty<Image> image;
}
Это позволяет вамслушать изменения данных корабля:
Starship ship = new Starship();
firstPaneController.setShip(ship);
secondPaneController.setShip(ship);
LoginController
private Starship ship;
public void setShip(Starship ship) {
this.ship = ship;
}
private void setAll(String user) {
ship.setCaptain(new CrewMember(user));
ship.getCrew().setAll(Stream.generate(() -> new CrewMember(user))
.limit(8)
.toArray(CrewMember[]::new));
}
PersonnelController
private Label[] crewNameLabels;
private ImageView[] crewImageViews;
@Override
public void initialize(URL location, ResourceBundle resources) {
crewNameLabels = new Label[] { crew1, crew2, crew3, crew4, crew5, crew6, crew7, crew8 };
crewImageViews = new ImageView[] {
commandOfficer,
firstOfficer,
commOfficer,
engineOfficer,
helmsman,
navigator,
medOfficer,
nurse
};
}
private final InvalidationListener crewUpdater = o -> {
int newCrewSize = 0;
if (ship != null) {
List<Crew> crew = ship.getCrew();
newCrewSize = ship.getCrew().size();
if (newCrewSize > crewNameLabels.length) {
newCrewSize = crewNameLabels.length;
}
for (int i = 0; i < newCrewSize; i++) {
CrewMember c = crew.get(i);
crewNameLabels[i].textProperty().bind(c.nameProperty());
crewImageViews[i].imageProperty().bind(c.imageProperty());
}
}
// unbind everything that has no corresponding CrewMember
for (int i = newCrewSize; i < crewNameLabels.length; i++) {
crewNameLabels[i].textProperty().unbind();
crewNameLabels[i].setText("");
crewImageViews[i].imageProperty().unbind();
crewImageViews[i].setImage(null);
}
};
private final InvalidationListener captainUpdater = o -> {
CrewMember captain = null;
if (ship != null) {
captain = ship.getCaptain();
}
if (captain == null) {
welcomeMsg.textProperty().unbind();
welcomeMsg.setText("");
} else {
welcomeMessage.bind(Bindings.concat("Welcome, ", captain.nameProperty()));
}
};
private Starship ship;
public void setShip(Starship ship) {
if (this.ship != null) {
// remove old listener when replacing the ship
this.ship.getCrew().removeListener(crewUpdater);
this.ship.captainProperty().removeListener(captainUpdater);
}
this.ship = ship;
if (ship != null) {
ship.getCrew().addListener(crewUpdater);
ship.captainProperty().addListener(captainUpdater);
shipName.textProperty().bind(ship.nameProperty());
} else {
shipName.textProperty().unbind();
shipName.setText("");
}
// update content
crewUpdater.invalidated(null);
captainUpdater.invalidated(null);
}
Thisдолжен позволить вам обновить объект Starship
в любом месте потока приложения JavaFX и увидеть изменения в кадре персонала. Если сделать класс CrewMember
неизменным, это немного снизит сложность обновления, поскольку вам больше не нужно будет использовать привязки, а просто нужно выполнять назначения. Кроме того, только когда-либо наличие одного корабля + кадровой сцены позволит вам удалить логику освобождения, еще более упрощая логику ...