简体   繁体   English

使用正在运行的JavaFX应用程序,使用自己独立的控制器类打开一个新窗口

[英]With a running JavaFX application, open a new window with its own, separate controller class

I'm using SceneBuilder in conjunction with Netbeans' JavaFX library for this project. 我正在将SceneBuilder与Netbeans的JavaFX库结合使用。 I use Scenebuilder to create the fxml and netbeans for the controller classes. 我使用Scenebuilder为控制器类创建fxml和netbeans。 The goal is to build a fairly complex app that is to be deployed. 目标是构建一个相当复杂的应用程序。

I can launch a JavaFX application and hook up the controller class just fine. 我可以启动一个JavaFX应用程序并连接控制器类就好了。 However, when I try to open a new window I can't seem to bind a controller class to the new window. 但是,当我尝试打开一个新窗口时,我似乎无法将控制器类绑定到新窗口。 To keep things simple I would like to have a separate controller class for the new window due to a complex back-end. 为了简单起见,我希望新窗口有一个单独的控制器类,因为后端很复杂。

TL;DR -- Trying to open a new window on JavaFX application with a controller class. TL; DR - 尝试使用控制器类在JavaFX应用程序上打开一个新窗口。 Controller class isn't binding. 控制器类没有绑定。

Code samples below 代码示例如下

Model class -- wrapper for launching the application 模型类 - 用于启动应用程序的包装器

public class Model extends Application{
    public static void main(String[] args){
         Application.launch(Model.class, args);
    }
    @Override
    public void start(Stage stage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
        stage.setScene(new Scene(root));
        stage.show();
    }
}

Sample.fxml -- fxml file for the main application Sample.fxml - 主应用程序的fxml文件

Sample.java -- extends Initializable, is the controller class for Sample.fxml. Sample.java - extends Initializable,是Sample.fxml的控制器类。 Below is code snippet where I try to open the new window titled "ServerConfigChooser 下面是我尝试打开标题为“ServerConfigChooser”的新窗口的代码片段

try{
    Parent root = FXMLLoader.load(getClass().getResource("ServerConfigChooser.fxml"));
    FXMLLoader loader = new FXMLLoader(getClass().getResource("ServerConfigChooser.fxml"));
    ServerConfigChooser controller = new ServerConfigChooser();

    loader.setController(controller);
    loader.setRoot(root);

    Stage stage = new Stage();
    stage.setScene(new Scene(root));
    stage.show();
} catch (IOException ex)

ServerConfigChooser.java -- implements Initializable ServerConfigChooser.java - 实现Initializable

This is where I have the problems. 这就是我遇到问题的地方。 I cannot simply declare variables with the same fxid as the variables in the .fxml file. 我不能简单地使用与.fxml文件中的变量相同的fxid声明变量。 The initialize() method does not fire when the class is called. 调用类时,不会触发initialize()方法。

The reason for the constructor in the ServerConfigChooser class is that I could not fire the initialize() method automatically. ServerConfigChooser类中构造函数的原因是我无法自动触发initialize()方法。 I fire that manually within the constructor. 我在构造函数中手动触发。

Any solutions are welcome! 欢迎任何解决方案!

Don't load the FXML twice like that. 不要像这样加载FXML两次。 You can load multiple times the same .fxml document (multiple scene graph / controllers) but if you want to do together loading the scene graph and initializing the controller you have to call the fxml loader only once. 您可以加载多次相同的.fxml文档(多个场景图/控制器),但如果您想一起加载场景图并初始化控制器,则必须只调用一次fxml加载器。

Here is an example 这是一个例子

    FXMLLoader loader = new FXMLLoader(getClass().getResource("ServerConfigChooser.fxml"));
    ServerConfigChooser controller = new ServerConfigChooser();
    loader.setController(controller);
    loader.setRoot(controller);
    Parent root;
    try {
        root = (Parent) loader.load();
        Scene scene = new Scene(root, 320, 200);
        Stage stage = new Stage();
        stage.setScene(scene);
        stage.show();
    } catch (IOException ex) {
        Logger.getLogger(ServerConfigChooser.class.getName()).log(Level.SEVERE, null, ex);
    }

Note that 注意

  • your controller should extend the node type of the root node of your .fxml document 您的控制器应该扩展.fxml文档的根节点的节点类型
  • your .fxml document should use fxroot construct, see this doc (you can set this in scene builder) 您的.fxml文档应该使用fxroot构造,请参阅此文档 (您可以在场景构建器中设置此文档
  • you should remove the controller from the fxml root element. 你应该从fxml根元素中删除控制器。 It will conflict with this way of using the FXMLLoader class 它将与使用FXMLLoader类的这种方式冲突

For example the controller class 例如控制器类

public class ServerConfigChooser extends AnchorPane implements Initializable {
   ...
}

And the .fxml 和.fxml

<fx:root type="javafx.scene.layout.AnchorPane" id="AnchorPane" prefHeight="200.0" prefWidth="320.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2">

The problem here is probably how you are loading the ServerConfigChooser (I get the feeling the FXML is loaded twice or something like that). 这里的问题可能是你如何加载ServerConfigChooser (我觉得FXML加载两次或类似的东西)。 The following should work: 以下应该有效:

try {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("ServerConfigChooser.fxml"));
    ServerConfigChooser controller = new ServerConfigChooser();
    loader.setController(controller);
    Parent root = (Parent) loader.load();

    Stage stage = new Stage();
    stage.setScene(new Scene(root));
    stage.show();
}
catch(...) {...}

Also check that you don't specify fx:controller in ServerConfigChooser.fxml (could conflict, haven't actually tried). 另请检查您是否在ServerConfigChooser.fxml 指定fx:controller (可能会发生冲突,尚未尝试过)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM