Détecter lorsque la scène est de nouveau mise au point et que la scène est chargée
J'ai une scène parent, au-dessus de laquelle une fenêtre contextuelle peut être affichée. Voici le 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();
}
Avant d'afficher la fenêtre contextuelle, je brouille le nœud parent par la méthode setEffect (). Comment puis-je supprimer l'effet de flou lorsque la fenêtre contextuelle est fermée?
Dans mes tentatives, je suis toujours confronté à un problème avec malgré le fait que le popup disparaît déjà, les éléments annotés par @FXML dans le contrôleur d'écran parent sont nuls, mais ils sont déjà visibles et ne sont pas masqués par le popup
Existe-t-il un écouteur qui gère les événements lorsque la scène n'est pas bloquée et que la scène est déjà chargée, afin que je puisse interagir avec les objets @FXML?
Voici une partie du contrôleur de scène qui se trouve dans la phase principale:
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();
}
}
Code de classe SceneManager (@Data est une annotation lombok, peut être remplacé par des getters ad setters):
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()));
}
}
Classe AppKitty:
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>
Réponses
Selon votre code, vous devez inclure les gestionnaires de fermeture pour l'étape popup au moment de la déclaration dans votre bloc statique. Vous pouvez inclure l'un des gestionnaires ci-dessous. (Dépend de vos besoins)
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()
});