JavaFx 处理程序覆盖
JavaFx handler override
我有一个从 fxml 构建器构建的 fxml 文件,我在 Java.
中通过加载器使用它
URL resource = getClass().getClassLoader().getResource("fxmlFile.fxml");
FXMLLoader loader = new FXMLLoader(resource, resourceBundle);
Pane rootPane = (Pane) loader.load();
这个 fxml 文件将点击事件映射到我的 class;
<Group id="Group" layoutX="0.0" layoutY="0.0" onMouseReleased="#handleThis" scaleX="1.0" scaleY="1.0">
...
<Group/>
所以我在 class 中实现了我的处理程序,我们称它为 MyClass;
public class MyClass {
public void createScene() throws IOException
{
URL resource = getClass().getClassLoader().getResource("fxmlFile.fxml");
FXMLLoader loader = new FXMLLoader(resource, resourceBundle);
Pane rootPane = (Pane) loader.load();
...
}
@FXML
public void handleThis(ActionEvent event) {
System.out.println("from MyClass");
}
...
}
现在我将 MyClass 扩展为 MyExtendedClass 并覆盖 handleThis 方法;
public class MyExtendedClass extends MyClass {
@Override
public void handleThis(ActionEvent event) {
System.out.println("from MyExtendedClass");
}
}
我的问题是,我无法在我的扩展 class 中处理 handle 方法。它不会覆盖它。我怎样才能让它打印 "from MyExtendedClass" 而不是 "from MyClass"?
当在 MyExtendedClass 实例上调用 createScene()
时,FXMLLoader 解析 FXML 文件,读取 fx:controller="MyClass"
属性并实例化一个 new 对象输入 MyClass。这就是为什么始终调用基方法的原因。 FXMLLoader 不知道 MyExtendedClass。
有一种 - 骇人听闻的 - 方法可以实现你想要的(即在 MyClass 中进行加载并仍然在 FXML 中定义控制器):
public class MyClass
{
public void createScene()
{
try
{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXML.fxml"));
// set a controller factory that returns this instance as controller
// (works in this case, but not recommended)
loader.setControllerFactory(controllerType -> this);
pane = (Pane) loader.load();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
}
实例化控制器并将其传递给 FXMLLoader 会更清晰。
为此,必须从 FXML 文件中删除 fx:controller=""
属性。
public class Main extends Application
{
@Override
public void start(Stage primaryStage) throws Exception
{
MyClass controller = new MyExtendedClass();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXML.fxml"));
loader.setController(controller);
Pane pane = (Pane) loader.load();
primaryStage.setScene(new Scene(pane));
primaryStage.show();
}
public static void main(String[] args)
{
launch(args);
}
}
或者使用fx:controller="MyClass"
在FXML文件中定义基本类型,让控制器工厂决定实际实现。
public class Main extends Application
{
@Override
public void start(Stage primaryStage) throws Exception
{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXML.fxml"));
loader.setControllerFactory(controllerType -> {
if (MyClass.class.equals(controllerType))
return new MyExtendedClass();
else
return null; // return some other controller
});
Pane pane = (Pane) loader.load();
MyClass controller = (MyClass) loader.getController();
primaryStage.setScene(new Scene(pane));
primaryStage.show();
}
public static void main(String[] args)
{
launch(args);
}
}
我有一个从 fxml 构建器构建的 fxml 文件,我在 Java.
中通过加载器使用它URL resource = getClass().getClassLoader().getResource("fxmlFile.fxml");
FXMLLoader loader = new FXMLLoader(resource, resourceBundle);
Pane rootPane = (Pane) loader.load();
这个 fxml 文件将点击事件映射到我的 class;
<Group id="Group" layoutX="0.0" layoutY="0.0" onMouseReleased="#handleThis" scaleX="1.0" scaleY="1.0">
...
<Group/>
所以我在 class 中实现了我的处理程序,我们称它为 MyClass;
public class MyClass {
public void createScene() throws IOException
{
URL resource = getClass().getClassLoader().getResource("fxmlFile.fxml");
FXMLLoader loader = new FXMLLoader(resource, resourceBundle);
Pane rootPane = (Pane) loader.load();
...
}
@FXML
public void handleThis(ActionEvent event) {
System.out.println("from MyClass");
}
...
}
现在我将 MyClass 扩展为 MyExtendedClass 并覆盖 handleThis 方法;
public class MyExtendedClass extends MyClass {
@Override
public void handleThis(ActionEvent event) {
System.out.println("from MyExtendedClass");
}
}
我的问题是,我无法在我的扩展 class 中处理 handle 方法。它不会覆盖它。我怎样才能让它打印 "from MyExtendedClass" 而不是 "from MyClass"?
当在 MyExtendedClass 实例上调用 createScene()
时,FXMLLoader 解析 FXML 文件,读取 fx:controller="MyClass"
属性并实例化一个 new 对象输入 MyClass。这就是为什么始终调用基方法的原因。 FXMLLoader 不知道 MyExtendedClass。
有一种 - 骇人听闻的 - 方法可以实现你想要的(即在 MyClass 中进行加载并仍然在 FXML 中定义控制器):
public class MyClass
{
public void createScene()
{
try
{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXML.fxml"));
// set a controller factory that returns this instance as controller
// (works in this case, but not recommended)
loader.setControllerFactory(controllerType -> this);
pane = (Pane) loader.load();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
}
实例化控制器并将其传递给 FXMLLoader 会更清晰。
为此,必须从 FXML 文件中删除 fx:controller=""
属性。
public class Main extends Application
{
@Override
public void start(Stage primaryStage) throws Exception
{
MyClass controller = new MyExtendedClass();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXML.fxml"));
loader.setController(controller);
Pane pane = (Pane) loader.load();
primaryStage.setScene(new Scene(pane));
primaryStage.show();
}
public static void main(String[] args)
{
launch(args);
}
}
或者使用fx:controller="MyClass"
在FXML文件中定义基本类型,让控制器工厂决定实际实现。
public class Main extends Application
{
@Override
public void start(Stage primaryStage) throws Exception
{
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXML.fxml"));
loader.setControllerFactory(controllerType -> {
if (MyClass.class.equals(controllerType))
return new MyExtendedClass();
else
return null; // return some other controller
});
Pane pane = (Pane) loader.load();
MyClass controller = (MyClass) loader.getController();
primaryStage.setScene(new Scene(pane));
primaryStage.show();
}
public static void main(String[] args)
{
launch(args);
}
}