Эффект масштаба для полноэкранного режима исчезает после переключения корневых узлов - PullRequest
0 голосов
/ 06 июня 2019

Я пытаюсь переключаться между корнями сцены, одновременно масштабируя их в полноэкранном режиме.

Я попробовал код в принятом ответе для этого вопроса , но я не могу перейти в полноэкранный режим, используя его, если я не скрою Сцену, а затем снова показываю ее в 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>
...