默认行为FXMLLoader
是创建控制器类的新实例并使用该实例作为控制器。
具体来说,FXMLLoader
做类似的事情:
- Read the root FXML element.
- If the root FXML element has a
fx:controller
attribute, then
- If a controller already exists, throw an exception, otherwise create an instance of the specified class1 and set that as the controller
- 继续解析 FXML 文件。如果元素有一个
fx:id
属性,并且控制器存在(通过任何机制),将这些字段注入到控制器中。类似地,将事件处理程序注册为对控制器实例中的方法的调用。
- Invoke
initialize()
在控制器上,如果控制器存在并且它有这样的方法。
所以,你问的问题是:
应用程序类可以是控制器类吗
是的,但这可能是一个糟糕的主意。如果您简单地指定Application
子类作为控制器类使用fx:controller
,然后是第二个实例Application
子类被创建,@FXML
- 带注释的字段被注入到第二个实例上,并且initialize()
在第二个实例上调用方法。显然,@FXML
-字段永远不会在其实例上初始化start(...)
被调用,并且initialize()
永远不会在该实例上调用方法。
你的意思可能是:
启动时创建的应用程序类实例可以用作控制器吗?
答案也是肯定的,除了您打算立即丢弃的非常小的演示程序之外,这也可能是一个非常糟糕的主意。你会这样做
public class MyApp extends Application {
@FXML
private Node someNode ;
public void initialize() {
// do something with someNode
}
@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/path/to/fxml/file.fxml"));
loader.setController(this);
Parent root = loader.load();
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
请注意,要使用此代码,您的 FXML 文件must not have a fx:controller
属性。
这样做的问题是你没有分离性,也没有灵活性。 (例如,如果您在 FXML 文件中的某个位置创建了视图的第二个实例,那么您最终会得到第二个实例Application
子类实例,这充其量是违反直觉的(一个应用程序有两个Application
实例...).)
因此,我主张基本上在每种情况下都为控制器使用单独的类。这Application
子类应包含最少的代码,并且仅用于启动应用程序。
1 This step is actually a little more complex. If a class is specified in the fx:controller
attribute, and no controller already exists, the FXMLLoader
checks for a controllerFactory http://docs.oracle.com/javase/8/javafx/api/javafx/fxml/FXMLLoader.html#setControllerFactory-javafx.util.Callback-. If one exists, then the controller is set as the result of passing the specified Class
to the controllerFactory
's call()
method, otherwise it is created by calling newInstance()
on the specified class (effectively calling its no-argument constructor).