[英]Is it possible to detect when the mouse cursor is over a hidden stage or scene in JavaFX?
[英]Detect when stage again in focus and scene is loaded
我有一個父階段,可以在其上顯示彈出窗口。 這是代碼:
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() 方法模糊了父節點。 彈出窗口關閉時如何去除模糊效果?
在我的嘗試中,盡管彈出窗口已經消失,但我總是面臨問題,在父屏幕控制器中由 @FXML 注釋的元素為空,但它們已經可見並且不會被彈出窗口隱藏
是否有任何偵聽器可以在舞台未阻塞且場景已加載時處理事件,以便我可以與 @FXML 對象進行交互?
這是在初級階段設置的場景控制器的一部分:
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 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 類:
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>
根據您的代碼,您需要在靜態塊中聲明時包含彈出階段的關閉處理程序。 您可以包含以下任何處理程序..(取決於您的需要)
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()
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.