检测何时再次聚焦并加载场景 [英] Detect when stage again in focus and scene is loaded

查看:30
本文介绍了检测何时再次聚焦并加载场景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个父级,可以在其上显示弹出窗口. 这是代码:

I have a parent stage, on top of which popup can be shown. Here is 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();
    }

在显示弹出窗口之前,我通过setEffect()方法模糊了父节点. 关闭弹出窗口后如何消除模糊效果?

Before I show popup, I blur the parent node by setEffect() method. How can I remove the blur effect when popup is closed?

在我的尝试中,尽管弹出窗口已经消失,但我始终面临着问题,在父屏幕控制器中由@FXML注释的元素为null,但是它们已经可见并且不会被弹出窗口隐藏

In my attempts I always facing issue with despite popup already dissapear, elements annotated by @FXML in parent screen controller is null, but they alreadt visible and dont hidden by popup

有没有侦听器,可以在舞台未被阻塞且场景已加载时处理事件,因此我可以与@FXML对象进行交互?

Is there any listener, which handle events when stage not blocked and scene is already loaded, so I can interact with @FXML objects?

这是场景控制器的一部分,它设置在初级阶段:

Here is part of scene controller which set in primary stage:

        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类代码(@Data是lombok批注,可以用getters广告setter代替):

SceneManager class code(@Data is lombok annotation, can be replaced by 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()));
    }
}

AppKitty类:

AppKitty class:

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:

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>

推荐答案

根据您的代码,您需要在静态块中包含声明时弹出窗口的关闭处理程序.您可以包括以下任何处理程序..(视您的需要而定)

As per your code, you need to include the close handlers for the popup stage at the time of declaration in your static block. You can include any of the below handlers.. (depends as per your need)

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

这篇关于检测何时再次聚焦并加载场景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆