Я пытаюсь переключаться между корнями сцены, одновременно масштабируя их в полноэкранном режиме.
Я попробовал код в принятом ответе для этого вопроса , но я не могу перейти в полноэкранный режим, используя его, если я не скрою Сцену, а затем снова показываю ее в letterbox()
метод.
Изначально это по крайней мере приводит к тому, что параметры сцены масштабируются в полноэкранном режиме должным образом, но когда я возвращаюсь к титульной сцене, эффект исчезает.
Как я могу заставить эту программу правильно масштабировать каждую сцену?
Я попытался создать минимальный, полный и проверяемый пример, но это сложно, потому что я неопытен в JavaFX и из-за природы использования JavaFX с несколькими файлами FXML.
Я полагаю, что ответ на мою проблему лежит в первом поле кода, обозначенном здесь как "MCVE Class". Однако, если вы хотите запустить его самостоятельно, вам придется поместить другие блоки кода в их собственные файлы.
Я не включил файлы CSS для экономии места, и эти сцены могут выглядеть странно без них.
Пожалуйста, дайте мне знать, если у вас есть какие-либо комментарии или вопросы, и спасибо за чтение.
MCVE Класс
public class MCVE extends Application {
private final static Stage STAGE = new Stage();
private static boolean isFullscreen = false;
@Override
public void start(Stage primaryStage) throws Exception {
Pane root = FXMLLoader.load(getClass().getResource("/fxml/title_screen.fxml"));
Scene firstScene = new Scene(root, 1280.0, 800.0);
STAGE.setScene(firstScene);
STAGE.setTitle("Evil Wizard");
STAGE.setResizable(false);
STAGE.show();
}
public void activateOptionsScene() throws Exception {
Pane root = FXMLLoader.load(getClass().getResource("/fxml/options_screen.fxml"));
STAGE.getScene().setRoot(root);
}
public void activateTitleScene() throws Exception {
Pane root = FXMLLoader.load(getClass().getResource("/fxml/title_screen.fxml"));
STAGE.getScene().setRoot(root);
}
public void toggleFullscreen() {
letterbox(STAGE.getScene(), (Pane) STAGE.getScene().getRoot());
STAGE.setFullScreen(!isFullscreen);
isFullscreen = !isFullscreen;
}
/**
* Copied from
* https://stackoverflow.com/questions/16606162/javafx-fullscreen-resizing-elements-based-upon-screen-size
* <p>
* author: jewelsea
* date retrieved: 6-5-19
* <p>
* Resizes elements when switching between fullscreen and windowed mode.
*/
private static class SceneSizeChangeListener implements ChangeListener<Number> {
private final Scene scene;
private final double ratio;
private final double initHeight;
private final double initWidth;
private final Pane contentPane;
private SceneSizeChangeListener(Scene scene, double ratio, double initHeight, double initWidth, Pane contentPane) {
this.scene = scene;
this.ratio = ratio;
this.initHeight = initHeight;
this.initWidth = initWidth;
this.contentPane = contentPane;
}
@Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue) {
final double newWidth = scene.getWidth();
final double newHeight = scene.getHeight();
double scaleFactor;
if (newWidth / newHeight > ratio)
scaleFactor = newHeight / initHeight;
else
scaleFactor = newWidth / initWidth;
System.out.println(scaleFactor + " " + (scaleFactor >= 1));
if (scaleFactor >= 1) {
Scale scale = new Scale(scaleFactor, scaleFactor);
scale.setPivotX(0);
scale.setPivotY(0);
scene.getRoot().getTransforms().setAll(scale);
contentPane.setPrefWidth(newWidth / scaleFactor);
contentPane.setPrefHeight(newHeight / scaleFactor);
} else {
contentPane.setPrefWidth(Math.max(initWidth, newWidth));
contentPane.setPrefHeight(Math.max(initHeight, newHeight));
}
}
}
/**
* Modified version of letterbox method from the same source as the above
* static class. Forces application to hide and then show itself again.
*
* @param scene The Scene object to scale.
* @param contentPane The Pane to scale.
*/
public void letterbox(final Scene scene, final Pane contentPane) {
STAGE.hide();
final double initWidth = scene.getWidth();
final double initHeight = scene.getHeight();
final double ratio = initWidth / initHeight;
SceneSizeChangeListener sizeListener = new SceneSizeChangeListener(scene, ratio, initHeight, initWidth, contentPane);
scene.widthProperty().addListener(sizeListener);
scene.heightProperty().addListener(sizeListener);
STAGE.setFullScreen(!Organizer.isFullscreen());
Organizer.setIsFullscreen(Organizer.isFullscreen());
STAGE.show();
}
}
Класс заголовка экрана контроллера
package controllers;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import main.MCVE;
public class TitleScreenController {
@FXML
private Button optionsButton;
public void goToOptionsScene() throws Exception {
new MCVE().activateOptionsScene();
}
}
Опции экрана класса контроллера
package controllers;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import main.MCVE;
public class OptionsScreenController {
@FXML
private Button returnButton;
public void toggleFullscreen() {
new MCVE().toggleFullscreen();
}
public void returnToTitleScreen() throws Exception {
new MCVE().activateTitleScene();
}
}
title_screen.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="1280.0" style="-fx-background-color: BLACK;" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.TitleScreenController">
<children>
<Label layoutX="310.0" layoutY="105.0" scaleX="2.0" scaleY="2.0" text="Evil Wizard" textFill="WHITE" underline="true">
<font>
<Font name="Dumbledor 1" size="96.0" />
</font>
</Label>
<VBox fillWidth="false" layoutX="279.0" layoutY="373.0" prefHeight="325.0" prefWidth="500.0" spacing="15.0" stylesheets="@../css/buttons_sidebar.css">
<children>
<Button fx:id="continueButton" alignment="CENTER" mnemonicParsing="false" prefHeight="0.0" prefWidth="999.0" text=" Continue " visible="false">
<font>
<Font name="Caladea Bold" size="22.0" />
</font>
</Button>
<Button fx:id="startButton" alignment="CENTER" layoutX="10.0" layoutY="10.0" mnemonicParsing="false" onAction="#startGame" text=" Start ">
<font>
<Font name="Charis SIL Bold" size="22.0" />
</font>
</Button>
<Button fx:id="loadButton" alignment="CENTER" layoutX="10.0" layoutY="123.0" mnemonicParsing="false" text=" Load ">
<font>
<Font name="Charis SIL Bold" size="22.0" />
</font>
</Button>
<Button fx:id="optionsButton" alignment="CENTER" layoutX="55.0" layoutY="184.0" mnemonicParsing="false" onAction="#goToOptionsScene" text=" Options ">
<font>
<Font name="Charis SIL Bold" size="22.0" />
</font>
</Button>
<Button fx:id="exitButton" alignment="CENTER" layoutX="10.0" layoutY="236.0" mnemonicParsing="false" onAction="#exitGame" text=" Exit ">
<font>
<Font name="Charis SIL Bold" size="22.0" />
</font>
</Button>
</children>
</VBox>
</children>
</Pane>
options_screen.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="1280.0" style="-fx-background-color: BLACK;" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.OptionsScreenController">
<children>
<VBox layoutX="30.0" layoutY="725.0" prefHeight="38.0" prefWidth="171.0">
<children>
<Button fx:id="returnButton" mnemonicParsing="false" onAction="#returnToTitleScreen" prefHeight="38.0" prefWidth="188.0" stylesheets="@../css/buttons_menu.css" text=" Return ">
<font>
<Font name="Caladea" size="13.0" />
</font>
</Button>
</children>
</VBox>
<CheckBox fx:id="fullscreenCheckBox" layoutX="30.0" layoutY="37.0" mnemonicParsing="false" onAction="#toggleFullscreen" text="Fullscreen" textFill="WHITE">
<font>
<Font name="Old Style" size="22.0" />
</font>
</CheckBox>
</children>
</Pane>