如何在控制器类的javafx应用程序中交换屏幕?

B Y*_*Y E 19 javafx javafx-2

嘿,我在网上搜索了一段时间,但我找不到解决以下问题的方法:

在javafx中你有3个基本文件; controller-class,fxml文件和应用程序类.现在我想在控制器中做出反应点击按钮(效果非常好)并更改该点击的屏幕(你通常使用stage.setScreen()),但我没有参考舞台(你可以在应用程序类中找到).

应用程序示例:

public class JavaFXApplication4 extends Application {

@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));

    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
}

/**
 * The main() method is ignored in correctly deployed JavaFX application.
 * main() serves only as fallback in case the application can not be
 * launched through deployment artifacts, e.g., in IDEs with limited FX
 * support. NetBeans ignores main().
 *
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}
}
Run Code Online (Sandbox Code Playgroud)

FXML-样品:

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

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="200.0" prefWidth="320.0"  xmlns:fx="http://javafx.com/fxml" fx:controller="javafxapplication4.SampleController">
  <children>
  <Button id="button" fx:id="nextScreen" layoutX="126.0" layoutY="90.0" onAction="#handleButtonAction" text="Next Screen" />
  <Label fx:id="label" layoutX="126.0" layoutY="120.0" minHeight="16.0" minWidth="69.0" />
  </children>
</AnchorPane>
Run Code Online (Sandbox Code Playgroud)

控制器 - 示例:

public class SampleController implements Initializable {

@FXML
private Label label;

@FXML
private void handleButtonAction(ActionEvent event) {
    System.out.println("You clicked me!");
    label.setText("Hello World!");
    //Here I want to swap the screen!
}

@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
}    
}
Run Code Online (Sandbox Code Playgroud)

我会感谢任何帮助.

Ulu*_*Biy 31

@FXML
private void handleButtonAction(ActionEvent event) {
    System.out.println("You clicked me!");
    label.setText("Hello World!");
    //Here I want to swap the screen!

    Stage stageTheEventSourceNodeBelongs = (Stage) ((Node)event.getSource()).getScene().getWindow();
    // OR
    Stage stageTheLabelBelongs = (Stage) label.getScene().getWindow();
    // these two of them return the same stage
    // Swap screen
    stage.setScene(new Scene(new Pane()));
}
Run Code Online (Sandbox Code Playgroud)


Wal*_*rer 13

我在进入Java并尝试解决同样的问题时发现了这个老问题.因为我希望场景能够记住开关之间的内容,所以我无法使用接受的答案,因为当在场景之间切换时,它会再次实例化它们(失去它们之前的状态).

无论如何,接受的答案和类似问题答案给了我一些关于如何在不失去状态的情况下切换场景的提示.主要思想是将场景的实例注入另一个控制器,这样控制器不需要反复实例化一个新场景,但可以使用已经存在的实例(具有其状态).

所以这是实例化场景的主类:

public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        // getting loader and a pane for the first scene. 
        // loader will then give a possibility to get related controller
        FXMLLoader firstPaneLoader = new FXMLLoader(getClass().getResource("firstLayout.fxml"));
        Parent firstPane = firstPaneLoader.load();
        Scene firstScene = new Scene(firstPane, 300, 275);

        // getting loader and a pane for the second scene
        FXMLLoader secondPageLoader = new FXMLLoader(getClass().getResource("secondLayout.fxml"));
        Parent secondPane = secondPageLoader.load();
        Scene secondScene = new Scene(secondPane, 300, 275);

        // injecting second scene into the controller of the first scene
        FirstController firstPaneController = (FirstController) firstPaneLoader.getController();
        firstPaneController.setSecondScene(secondScene);

        // injecting first scene into the controller of the second scene
        SecondController secondPaneController = (SecondController) secondPageLoader.getController();
        secondPaneController.setFirstScene(firstScene);

        primaryStage.setTitle("Switching scenes");
        primaryStage.setScene(firstScene);
        primaryStage.show();
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是两个控制器:

public class FirstController {

    private Scene secondScene;

    public void setSecondScene(Scene scene) {
        secondScene = scene;
    }

    public void openSecondScene(ActionEvent actionEvent) {
        Stage primaryStage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
        primaryStage.setScene(secondScene);
    }
}
Run Code Online (Sandbox Code Playgroud)

是的,第二个看起来是一样的(某些逻辑可能是共享的,但当前状态足以作为概念证明)

public class SecondController {

    private Scene firstScene;

    public void setFirstScene(Scene scene) {
        firstScene = scene;
    }

    public void openFirstScene(ActionEvent actionEvent) {    
        Stage primaryStage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow();
        primaryStage.setScene(firstScene);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 天啊,这救了我的命!我一直在网上搜索这样的东西,因为所有其他的例子每次都从文件加载资源但是我需要保存场景对象所以谢谢! (4认同)