在 windows 之间切换时如何阻止 JavaFx Slider 控件重置为其默认值

How to stop JavaFx Slider controls from resetting to their default values when switching between windows

我在 SceneBuilder 中为 javafx 构建了一堆 fxml windows。当我在我的设置 window 和我的主菜单之间切换时,滑块(用于各种音量)重置为它们的原始值,但是我希望它们保持上次 window 时的值打开。

我已经尝试在初始化中设置值并通过 class 设置一个变量,该变量在启动时被更改并用于设置滑块,但这也没有用。

FXML

<!-- The slider code (scenebuilder forces me to choose a value) ->
<Slider fx:id="soundfxSlider" onMouseDragged="#updateSFX" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="50.0" />
<Slider fx:id="musicSlider" minorTickCount="1" onMouseDragged="#updateMusic" showTickLabels="true" showTickMarks="true" snapToTicks="true" />

切换时主菜单和其他windows访问的启动方法

static void launchScreen(String fileName) {
        fileName = "/screens/" + fileName + ".fxml";
        try {
            Parent root = FXMLLoader.load(MainMenuController.class.getResource(fileName));
            Scene scene = new Scene(root);
            stage.setTitle("Fortress Combat");
            stage.setScene(scene);
            stage.show();
            stage.setOnCloseRequest(t -> {
                Platform.exit();
                System.exit(420);
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

设置控制器

public class SettingsController {

    @FXML // fx:id="soundfxSlider"
    private Slider soundfxSlider; // Value injected by FXMLLoader

    @FXML // fx:id="musicSlider"
    private Slider musicSlider; // Value injected by FXMLLoader

    @FXML
    void updateMusic(MouseEvent event) {
        double musicVolume =  musicSlider.getValue();
        //setMusicSlider(musicVolume);
        Launcher.adjustVolume(musicVolume);
    }

    @FXML
    void updateSFX(MouseEvent event) {
        double vol = soundfxSlider.getValue();
        //setSoundfxSlider(vol);
        Launcher.adjustSfx(vol);
    }

    private void setMusicSlider(double sliderVal) {
        musicSlider.setValue(sliderVal);
    }

    private void setSoundfxSlider(double sfxVal) {
        soundfxSlider.setValue(sfxVal);
    }

    @FXML
    void playTestSfx(ActionEvent event) {
        Launcher.playTestSFX();
    }

    @FXML
    void goBack(ActionEvent event) {
        Launcher.launchScreen("main_menu");
    }

    @FXML // This method is called by the FXMLLoader when initialization is complete
    void initialize() {
        assert soundfxSlider != null : "fx:id=\"soundfxSlider\" was not injected: check your FXML file 'settings.fxml'.";
        assert musicSlider != null : "fx:id=\"musicSlider\" was not injected: check your FXML file 'settings.fxml'.";
    }

如果没有为 fxml 中的滑块提供值,它们将采用默认值 0 - 似乎默认值是强制的,并且当 windows 切换时它不会 "remember"。

我相信我理解为什么在打开 new window 或者加载 window。

如果您看一下下面的代码,我们会发现您通过使用作为参数给定的名称加载 FXML 创建了一个新父级,之后您将新场景设置到您的舞台。从这里要注意的关键是你 create 一个 new parent and scene 不知道任何值设置你在其他场景中的滑块.

static void launchScreen(String fileName) {
    fileName = "/screens/" + fileName + ".fxml";
    try {
        Parent root =            
        FXMLLoader.load(MainMenuController.class.getResource(fileName));
        Scene scene = new Scene(root);
        stage.setTitle("Fortress Combat");
        stage.setScene(scene);
        stage.show();
        stage.setOnCloseRequest(t -> {
            Platform.exit();
            System.exit(420);
        });
    } catch (IOException e) {
        e.printStackTrace();
    }
}

几点建议:

  1. 保存实际场景,然后如果文件名参数对应于一个已经创建的场景,那么你真的可以 "switch" 场景而不是创建一个新场景。

下面是一个快速制作的示例,其中包含一个硬编码的 if 语句,它只是为了向您展示我的意思,但我相信您可以用更少的重复代码更好地解决它。

private Scene sceneA;

static void launchScreen(String fileName) {
    if(fileName.equals("sceneA") && sceneA != null){
         /*if we want to open up sceneA and it has been created before (meaning it's not null) then open the already existing scene.*/
            stage.setTitle("Fortress Combat");
            stage.setScene(sceneA);
            stage.show();
            stage.setOnCloseRequest(t -> {
                Platform.exit();
                System.exit(420);
            });

    }else{
        fileName = "/screens/" + fileName + ".fxml";
        try {
            Parent root =            
            FXMLLoader.load(MainMenuController.class.getResource(fileName));
            Scene scene = new Scene(root);
            stage.setTitle("Fortress Combat");
            stage.setScene(scene);
            stage.show();
            stage.setOnCloseRequest(t -> {
                Platform.exit();
                System.exit(420);
            });
        } catch (IOException e) {
            e.printStackTrace();
        }   
    }   
}
  1. 建议 2 是将它们存储在某个地方,可能在某个处理程序中 class 或者在一个文件中,如果您希望它们持久化。
  2. 或建议 3 可能是在您的控制器中声明一些静态变量,当滑块值发生变化时,您将这些变量设置为滑块的值。然后您可以通过访问静态变量在初始化方法中设置滑块值。

总之,以上就是我的想法,希望对大家有所帮助。 让我们知道结果如何:)