当前位置: 首页 > 知识库问答 >
问题:

如何在JavaFX中切换阶段

公冶元青
2023-03-14

共有1个答案

孔和畅
2023-03-14

如果我的应用程序应该在一个窗口中工作,我更喜欢使用GUI管理器单例类,它管理不断变化的窗口。下面我提供了一个使用这种机制的简单应用程序的完整代码。让我们假设所有文件都在一个包中,称为sample

java-在这里初始化JavaFX组件:

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import java.io.IOException;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
      FXMLLoader loader = new FXMLLoader();
      loader.setLocation(Main.class.getResource("/sample/root.fxml"));
      try{
        StackPane rootPane;
        rootPane = loader.load();
        GuiManager guiModel = GuiManager.getInstance();
        guiModel.setRootPane(rootPane);
        Scene scene = new Scene(rootPane);
        primaryStage.setScene(scene);
        primaryStage.show();
        guiModel.changeWindow("/sample/firstwindow.fxml");
      } catch (IOException exception) {
        exception.printStackTrace();
      }


    }

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

}

root.fxml-所有窗口都应该基于它:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.StackPane?>

<StackPane fx:id="rootPane"
           xmlns="http://javafx.com/javafx/8.0.60"
           xmlns:fx="http://javafx.com/fxml/1"
           prefWidth="1" prefHeight="1"/>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>

<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="sample.FirstWindowController">
    <Label text="First window"/>
    <Button text="Change window" onAction="#changeWindow"/>
</VBox>
package sample;

import javafx.fxml.FXML;

public class FirstWindowController {

  @FXML
  private void changeWindow() {
    GuiManager.getInstance().changeWindow("/sample/secondwindow.fxml");
  }
}
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>

<VBox xmlns:fx="http://javafx.com/fxml" fx:controller="sample.SecondWindowController" >
    <Label text="Second window"/>
    <Button text="Change window" onAction="#changeWindow"/>
</VBox>
package sample;

import javafx.fxml.FXML;

public class SecondWindowController {

  @FXML
  private void changeWindow() {
    GuiManager.getInstance().changeWindow("/sample/firstwindow.fxml");
  }
}
package sample;

import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.Window;
import java.io.IOException;

public class GuiManager {

  private StackPane rootPane;
  private static GuiManager instance;

  public static GuiManager getInstance() {
    if (instance == null) {
      instance = new GuiManager();
    }
    return instance;
  }

  private GuiManager() {}

  public void changeWindow(String path) {
    changeWindow(rootPane, path, this);
    rootPane.setPrefWidth(-1);
    rootPane.setPrefHeight(-1);
  }

  public static void changeWindow(Pane pane, String newWindowPath, Object callingController) {
    Window window = pane.getScene().getWindow();
    double x = window.getX() + getHorizontalMidpoint(window);
    double y = window.getY() + getVerticalMidpoint(window);

    ObservableList<Node> childrenList = pane.getChildren();
    removeAllIncludedChildren(childrenList);

    FXMLLoader loader = new FXMLLoader(callingController.getClass().getResource(newWindowPath));

    try {
      pane.getChildren().add(loader.load());
      Stage primaryStage = (Stage) window;
      primaryStage.setMinHeight(0);
      primaryStage.setMinWidth(0);
      window.sizeToScene();
      window.setX(x - getHorizontalMidpoint(window));
      window.setY(y - getVerticalMidpoint(window));
      primaryStage.setMinHeight(window.getHeight());
      primaryStage.setMinWidth(window.getWidth());
    } catch (IOException exception) {
      exception.printStackTrace();
    }
  }

  private static double getHorizontalMidpoint(Window window) {
    int horizontalBisectionCoefficient = 2;
    return window.getWidth() / horizontalBisectionCoefficient;
  }

  private static double getVerticalMidpoint(Window window) {
    int verticalBisectionCoefficient = 2;
    return window.getHeight() / verticalBisectionCoefficient;
  }

  private static void removeAllIncludedChildren(ObservableList<Node> childrenList) {
    for (int childIndex = 0; childIndex < childrenList.size(); childIndex++) {
      childrenList.remove(childIndex);
    }
  }

  public void setRootPane(StackPane rootPane) {
    this.rootPane = rootPane;
  }
}
 类似资料:
  • 我看了很多页,试图找出如何切换场景,但都没有成功。 我有一个计算器,我的目标是选择一个菜单选项来更改计算器(即:基础和科学)。现在我只是在测试,所以这里是我到目前为止与这个问题相关的代码(我使用的是场景生成器): 编辑我已经尝试了很多东西。不管怎样,我总是得到这个NullPointerException。我有一种感觉,这可能与在场景生成器中设置某些内容有关,但我就是找不到答案 工作代码: 我使用下

  • 我已经创建了一个类,它扩展了JavaFX的MenuBar,为我的应用程序创建了菜单栏。 默认情况下,我不会禁用专门的操作,比如打开/保存文件和运行模拟(它们确实是禁用的)。当用户运行应用程序时,他们可以在菜单文件中选择一个项目 我计划通过让每个组件给出它切换到的项目的列表来做到这一点,然后在创建组件时激活适当的项目。 但是,我不能从函数内部访问菜单列表(我尝试用< code>this.getMen

  • 我在Internet上到处找了找,但我没有找到这个简单问题的直接答案:在JavaFX应用程序中切换场景的最佳方法是什么?我有几个FXML文件和控制器,每一个,我希望能够在他们之间切换尽可能快(屏幕大小应该保持不变,所有关于窗口应该保持不变,除了内容)。 我可以考虑多种方法,最常见的方法是用FXMLLoader加载FXML文件,然后创建一个新场景,然后将这个场景设置为舞台,最后显示舞台。这是可行的,

  • 我想在2个不同的场景之间切换: 问题是当我从场景2切换到场景1时,场景1中加载的所有图像都不在那里(这很明显,因为我正在创建一个新场景,而不是“加载”场景1。 当我从场景2切换到场景1时,有什么方法可以保留已经加载的图像吗? 场景1