使用正在运行的 JavaFX 应用程序,打开一个带有自己的单独控制器类的新窗口
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21223893/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
With a running JavaFX application, open a new window with its own, separate controller class
提问by Kyte
I'm using SceneBuilder in conjunction with Netbeans' JavaFX library for this project. I use Scenebuilder to create the fxml and netbeans for the controller classes. The goal is to build a fairly complex app that is to be deployed.
我将 SceneBuilder 与 Netbeans 的 JavaFX 库结合用于此项目。我使用 Scenebuilder 为控制器类创建 fxml 和 netbeans。目标是构建一个要部署的相当复杂的应用程序。
I can launch a JavaFX application and hook up the controller class just fine. 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.
我可以启动一个 JavaFX 应用程序并连接控制器类就好了。但是,当我尝试打开一个新窗口时,我似乎无法将控制器类绑定到新窗口。为了简单起见,由于后端复杂,我想为新窗口创建一个单独的控制器类。
TL;DR -- Trying to open a new window on JavaFX application with a controller class. Controller class isn't binding.
TL;DR -- 尝试在带有控制器类的 JavaFX 应用程序上打开一个新窗口。控制器类没有绑定。
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. Below is code snippet where I try to open the new window titled "ServerConfigChooser
Sample.java -- extends Initializable,是 Sample.fxml 的控制器类。下面是我尝试打开标题为“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. The initialize() method does not fire when the class is called.
这是我有问题的地方。我不能简单地声明与 .fxml 文件中的变量具有相同 fxid 的变量。调用类时不会触发 initialize() 方法。
The reason for the constructor in the ServerConfigChooser class is that I could not fire the initialize() method automatically. I fire that manually within the constructor.
ServerConfigChooser 类中构造函数的原因是我无法自动触发 initialize() 方法。我在构造函数中手动触发。
Any solutions are welcome!
欢迎任何解决方案!
采纳答案by thomas.g
Don't load the FXML twice like that. 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 文档(多个场景图/控制器),但是如果您想一起加载场景图和初始化控制器,您只需调用一次 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
- your .fxml document should use fxroot construct, see this doc(you can set this in scene builder)
- you should remove the controller from the fxml root element. It will conflict with this way of using the
FXMLLoader
class
- 您的控制器应该扩展 .fxml 文档的根节点的节点类型
- 您的 .fxml 文档应使用 fxroot 构造,请参阅此文档(您可以在场景构建器中进行设置)
- 您应该从 fxml 根元素中删除控制器。它会与这种使用
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">
<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">
回答by Nikos Paraskevopoulos
The problem here is probably how you are loading the ServerConfigChooser
(I get the feeling the FXML is loaded twice or something like that). The following should work:
这里的问题可能是你如何加载ServerConfigChooser
(我觉得 FXML 被加载了两次或类似的东西)。以下应该工作:
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'tspecify fx:controller
in ServerConfigChooser.fxml
(could conflict, haven't actually tried).
还要检查您是否没有fx:controller
在中指定ServerConfigChooser.fxml
(可能会发生冲突,实际上还没有尝试过)。