如何在 javafx 中让一个场景覆盖另一个场景

how to have a scene over another in javafx

我正在写一个小游戏。而且我希望在游戏中间按下 esc 时显示模糊游戏菜单上的暂停菜单。 我所做的是制作一个新场景,其中有一个 stackPane 包裹着过去的根和暂停菜单根,然后我将过去的根的不透明度设置为 0.4。

然后当单击暂停菜单中的恢复按钮时,我将不透明度更改回 1 并将过去的场景设置在舞台上,但随后它被冻结了。有谁知道为什么?谁能帮我实现这个目标?

这是我制作新场景然后将其放在舞台上的部分:

        StackPane wrapper = new StackPane();
        previousScene = main.getPrimaryStage().getScene();
        previousScene.getRoot().setOpacity(.4);
        vBox.setId("pausedWrapper");
        wrapper.getChildren().add(previousScene.getRoot());
        wrapper.getChildren().add(vBox);
        scene = new Scene(wrapper, 1200, 700);
        return scene;

这是我将其改回原来位置的部分:

        resumeGame.setOnAction(event -> {
            System.out.println("game resumed!");
            previousScene.getRoot().setOpacity(1);
            main.getPrimaryStage().setScene(previousScene);
        });

但后来它不起作用,不透明度也没有变回正常,奇怪的是,当我检查盒子上的声音时,音乐正在播放,但盒子没有被选中,就像一切正常一样,但视图是冻结。

一个节点不能是两个不同场景图的一部分。这发生在 previousScene 的根代码中,因为它是 previousScene 和您在第一个代码块中创建的新场景的一部分。最有可能发生的事情是,当您将它添加到第二个场景时,它会从第一个场景中删除(尽管很难从您发布的代码中看出)。

考虑使用 Popup 在现有 window 之上显示 pauseMenu,或者只使用未修饰 StageStyle 的模态 Stage , 如以下 SSCCE:

import javafx.animation.Animation;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.effect.GaussianBlur;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Modality;
import javafx.stage.Popup;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;

public class PauseExample extends Application {

    @Override
    public void start(Stage primaryStage) {

        Rectangle rect = new Rectangle(50, 50, 50, 50);
        rect.setFill(Color.CORAL);

        TranslateTransition animation = createAnimation(rect);

        Button pauseButton = new Button("Pause");

        Pane pane = new Pane(rect);
        pane.setMinSize(600, 150);

        BorderPane root = new BorderPane(pane, null, null, pauseButton, new Label("This is\nthe main\nscene"));

        pauseButton.setOnAction(e -> {
            animation.pause();
            root.setEffect(new GaussianBlur());

            VBox pauseRoot = new VBox(5);
            pauseRoot.getChildren().add(new Label("Paused"));
            pauseRoot.setStyle("-fx-background-color: rgba(255, 255, 255, 0.8);");
            pauseRoot.setAlignment(Pos.CENTER);
            pauseRoot.setPadding(new Insets(20));

            Button resume = new Button("Resume");
            pauseRoot.getChildren().add(resume);

            Stage popupStage = new Stage(StageStyle.TRANSPARENT);
            popupStage.initOwner(primaryStage);
            popupStage.initModality(Modality.APPLICATION_MODAL);
            popupStage.setScene(new Scene(pauseRoot, Color.TRANSPARENT));


            resume.setOnAction(event -> {
                root.setEffect(null);
                animation.play();
                popupStage.hide();
            });

            popupStage.show();
        });

        BorderPane.setAlignment(pauseButton, Pos.CENTER);
        BorderPane.setMargin(pauseButton, new Insets(5));
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private TranslateTransition createAnimation(Rectangle rect) {
        TranslateTransition animation = new TranslateTransition(Duration.seconds(1), rect);
        animation.setByX(400);
        animation.setCycleCount(Animation.INDEFINITE);
        animation.setAutoReverse(true);
        animation.play();
        return animation;
    }

    public static void main(String[] args) {
        launch(args);
    }
}