Erkennen Sie, wenn die Bühne wieder scharf und die Szene geladen ist
Ich habe eine übergeordnete Phase, auf der ein Popup angezeigt werden kann. Hier ist Code:
private static Stage chooseBreedStage;
static {
chooseBreedStage = new Stage();
chooseBreedStage.setTitle("Choose breed");
chooseBreedStage.initOwner(AppKitty.getStage());
chooseBreedStage.initModality(Modality.WINDOW_MODAL);
chooseBreedStage.setScene(SceneManager.getInstance().getScene(SceneEnum.CHOOSE_BREED_SCREEN));
}
public void showChooseBreedPopup() {
chooseBreedStage.showAndWait();
}
Bevor ich Popup zeige, verwische ich den übergeordneten Knoten mit der Methode setEffect (). Wie kann ich den Unschärfeeffekt entfernen, wenn das Popup geschlossen ist?
Bei meinen Versuchen habe ich immer ein Problem damit, dass Elemente, die mit @FXML im übergeordneten Bildschirm-Controller mit Anmerkungen versehen sind, trotz bereits verschwundenem Popup immer null sind, aber bereits sichtbar sind und nicht durch Popup ausgeblendet werden
Gibt es einen Listener, der Ereignisse behandelt, wenn die Bühne nicht blockiert ist und die Szene bereits geladen ist, damit ich mit @ FXML-Objekten interagieren kann?
Hier ist ein Teil des Szenencontrollers, der in der Primärstufe eingestellt ist:
public class MainScreenController {
private GaussianBlur blur = new GaussianBlur();
@FXML
public StackPane mainScreen;
public void blurOn() {
mainScreen.setEffect(blur);
}
public void blurOff() {
mainScreen.setEffect(null);
}
public void makeTestClick(ActionEvent event) {
blurOn();
SceneManager.getInstance().getController(ChooseBreedScreenController.class)
.showChooseBreedPopup();
}
}
SceneManager-Klassencode (@Data ist eine Lombok-Anmerkung, kann durch Getter-Anzeigensetzer ersetzt werden):
public class SceneManager {
private final Map<SceneEnum, SceneData> sceneData = new HashMap<>();
@Data
private class SceneData {
private Scene scene;
private FXMLLoader loader;
private Controller controller;
SceneData(Scene scene, FXMLLoader loader) {
setScene(scene);
setLoader(loader);
setController(controller);
}
}
private static SceneManager instance = new SceneManager();
public static SceneManager getInstance() {
return instance;
}
private SceneManager() {
}
public <T extends Controller> T getController(Class<T> controllerClass) {
SceneEnum sceneEnum = getCorrespondingEnum(controllerClass);
if (sceneData.get(sceneEnum) == null || sceneData.get(sceneEnum).getController() == null) {
initSceneController(controllerClass);
}
return (T) sceneData.get(sceneEnum).getController();
}
public Controller getController(SceneEnum sceneEnum) {
return getController(sceneEnum.getControllerClass());
}
private <T extends Controller> void initSceneController(Class<T> controllerClass) {
try {
SceneEnum sceneEnum = getCorrespondingEnum(controllerClass);
if (sceneData.get(sceneEnum) == null) {
initScene(sceneEnum);
}
sceneData.get(sceneEnum).setController(controllerClass.getConstructor().newInstance());
} catch (Exception e) {
//todo here should be popup with error
}
}
private <T extends Controller> SceneEnum getCorrespondingEnum(Class<T> controllerClass) {
Optional<SceneEnum> desiredSceneEnum = Arrays.stream(SceneEnum.values())
.filter(sceneEnum -> controllerClass.isAssignableFrom(sceneEnum.getControllerClass()))
.findFirst();
return desiredSceneEnum.orElseGet(() -> {
//todo here should be shown popup with error
return null;
});
}
public Scene getScene(SceneEnum sceneEnum) {
if (sceneData.get(sceneEnum) == null) {
initScene(sceneEnum);
}
return sceneData.get(sceneEnum).getScene();
}
private void initScene(SceneEnum sceneEnum) {
ConsumerWithException<SceneEnum, IOException> loadingScene = sceneType -> {
FXMLLoader loader = getFxmlLoader(sceneEnum);
Scene scene = new Scene(loader.load());
sceneData.put(sceneEnum, new SceneData(scene, loader));
};
try {
loadingScene.accept(sceneEnum);
} catch (IOException initializeScreenException) {
try {
//Loading app error popup scene, before calling getController() method for
//this popup, to avoid recursion if loading app error popup scene producing exception as well
//(it may be in initScene method inside getController method)
loadingScene.accept(SceneEnum.APP_ERROR_POPUP);
getController(AppErrorPopupController.class)
.showAppErrorPopup(sceneEnum);
} catch (IOException initializeErrorPopupException) {
//todo make a better logging
initializeErrorPopupException.printStackTrace();
}
}
}
private FXMLLoader getFxmlLoader(SceneEnum scene){
return new FXMLLoader(this.getClass().getResource(scene.getScenePath()));
}
}
AppKitty-Klasse:
public class AppKitty extends Application {
private static Stage stage;
public static Stage getStage() {
return stage;
}
public static void setScene(SceneEnum sceneEnum) {
getStage().setScene(SceneManager.getInstance()
.getScene(sceneEnum));
}
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
stage = primaryStage;
primaryStage.setTitle("AppKitty");
primaryStage.setScene(SceneManager.getInstance().getScene(SceneEnum.MAIN_SCREEN));
primaryStage.show();
}
}
mainScreen.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<StackPane xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="applicationinterface.controllers.MainScreenController"
prefHeight="400.0" prefWidth="600.0"
fx:id="mainScreen"
stylesheets="@../styles/mainScreenBackground.css"
id="background_image">
<Label fx:id="title" text="What do you want?" alignment="TOP_CENTER"
stylesheets="@../styles/outline.css" styleClass="outline" StackPane.alignment="TOP_CENTER">
</Label>
<HBox
fx:id="bottomBar" id="outline.label" alignment="BOTTOM_CENTER"
stylesheets="@../styles/outline.css" spacing="20" StackPane.alignment="BOTTOM_CENTER">
<StackPane.margin>
<Insets bottom="10"/>
</StackPane.margin>
<Button fx:id="randomKittyButton" text="Random Kitty" onAction="#randomKittyClick" focusTraversable="false"
stylesheets="@../styles/buttonBorder.css" styleClass="button"/>
<Button fx:id="makeTestButton" text="Take the test" onAction="#makeTestClick" focusTraversable="false"
stylesheets="@../styles/buttonBorder.css" styleClass="button"/>
</HBox>
</StackPane>
Antworten
Gemäß Ihrem Code müssen Sie die Close-Handler für die Popup-Phase zum Zeitpunkt der Deklaration in Ihren statischen Block aufnehmen. Sie können einen der folgenden Handler einschließen. (Abhängig von Ihren Anforderungen.)
chooseBreedStage.setOnCloseRequest(e1->{
// Remove blur of AppKitty.getStage()
});
chooseBreedStage.addEventHandler(WindowEvent.WINDOW_HIDDEN,e1->{
// Remove blur of AppKitty.getStage()
});
chooseBreedStage.addEventFilter(WindowEvent.WINDOW_CLOSE_REQUEST,e1->{
// Remove blur of AppKitty.getStage()
});