在同一场景中加载新的fxml

And*_*dre 38 javafx scene fxml

我有2个fxml文件:

  • 布局(标题,菜单栏和内容)
  • Anchorpane(它应该放在其他fxml文件的内容中)

我想知道如何从"主"场景中加载内容空间内的第二个文件.在javaFX中工作是一件好事还是加载新场景更好?

我正在尝试做这样的事情,但它不起作用:

@FXML
private AnchorPane content;

@FXML
private void handleButtonAction(ActionEvent event) {        
    content = (AnchorPane) FXMLLoader.load("vista2.fxml");
}
Run Code Online (Sandbox Code Playgroud)

谢谢您的帮助.

jew*_*sea 69

为什么你的代码不起作用

加载器会创建一个新的AnchorPane,但您永远不会将新窗格添加到场景图中的父窗格.

快速解决

代替:

content = (AnchorPane) FXMLLoader.load("vista2.fxml");
Run Code Online (Sandbox Code Playgroud)

写:

content.getChildren().setAll(FXMLLoader.load("vista2.fxml"));
Run Code Online (Sandbox Code Playgroud)

用新视图替换内容子项.内容本身保留在场景图中,因此当您设置它的子项时,您也会同时将它们附加到场景图中.

您可能需要使用布局(例如,使用自动调整大小布局(如StackPanes而不是AnchorPanes)来获得所需的确切行为.

我不建议采用快速修复,而是建议查看下面链接的简单框架,因为这可能会为您提供更通用的机制来获取您想要的行为.

参考FXML导航框架

我创建了一个小框架,用于在主场景的一部分内外交换fxml控制的内容窗格.

该框架的机制与kithril的回答中提出的相同.

  1. 外部fxml的主窗格充当子窗格的持有者.
  2. 外部fxml的主控制器提供了一个可用于交换子窗格的公共方法.
  3. 使用外部布局的主控制器静态初始化便捷导航器类.
  4. 导航器提供了一个公共静态方法,用于将新的子窗格加载到主容器中(通过在主控制器上调用方法).
  5. 子窗格由导航器中的各自fxml加载器生成.

为何选择框架

这个框架对于回答你的问题似乎有些过分,也许就是这样.但是,我发现与FXML相关的两个问题最多的主题是:

  1. 在FXML生成的窗格之间导航(此问题).
  2. 如何在FXML控制器之间传递数据.

所以我觉得这个案例需要一个小的演示框架.

示例框架输出

第一个屏幕显示显示第一个视景的应用程序布局.内容是在主应用程序布局中定义的标题和aliceblue彩色可互换子内容窗格.

vista1

在下一个屏幕中,用户已导航到第二个视景,该视图保留主要布局中的常量标题,并用新的珊瑚色子内容窗格替换原始子窗格.新子项已从新的fxml文件加载.

vista2

寻找更实质的东西?

这个问题的样本框架比myburner.fx更广泛,更好地支持的轻量级框架.

寻找更简单的东西?

只需换出场景根:在JavaFX中更改场景.

其他选择?

动画过渡和其他:在JavaFX中的窗格之间切换


Tom*_*zyk 6

我不确定这是多么有效,但似乎很好,而且对于上述方法来说更简单.

https://www.youtube.com/watch?v=LDVztNtJWOo

据我所知,这里发生了什么(它与应用程序类中的Start()方法中发生的事情非常类似):

private void buttonGoToWindow3Action(ActionEvent event) throws IOException{
    Parent window3; //we need to load the layout that we want to swap
    window3 = (StackPane)FXMLLoader.load(getClass().getResource("/ScenePackage/FXMLWindow3"));

    Scene newScene; //then we create a new scene with our new layout
    newScene = new Scene(window3);

    Stage mainWindow; //Here is the magic. We get the reference to main Stage.
    mainWindow = (Stage)  ((Node)event.getSource()).getScene().getWindow();

    mainWindow.setScene(newScene); //here we simply set the new scene
}
Run Code Online (Sandbox Code Playgroud)

然而,我不是一个java专家,而且编程很新,所以如果有经验的人会对它进行评估会很好.

编辑:我发现更简单的方法;

转到MainApplication类并创建静态Stage parentWindow.

public static Stage parentWindow;
@Override
public void start(Stage stage) throws Exception {
    parentWindow = stage;

    Parent root = FXMLLoader.load(getClass().getResource("/ScenePackage/FXMLMainScene.fxml"));

    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
}
Run Code Online (Sandbox Code Playgroud)

现在您可以访问主舞台,因此您可以在程序中的任何位置执行类似的操作来更改场景:

    Parent window1;
    window1 = FXMLLoader.load(getClass().getResource("/ScenePackage/FXMLWindow1.fxml"));

    //Scene newSceneWindow1 = new Scene(window1);

    Stage mainStage;
    //mainStage = (Stage)  ((Node)event.getSource()).getScene().getWindow();
    mainStage = MainApplication.parentWindow;
    mainStage.getScene().setRoot(newSceneWindow1); //we dont need to change whole sceene, only set new root.
Run Code Online (Sandbox Code Playgroud)