javafx - 在控制器内加载 FXML 文件,但也使用 NetBeans 的“Make Controller”

Ign*_*mus 4 netbeans javafx fxml

在尝试加载 FXML 文件时,通常会执行如下操作:

FXMLLoader loader = FXMLLoader.load(getClass().getResource("File.fxml"));
Region root = loader.load();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试将加载代码放入控制器中以方便“调用者”时,我执行了以下操作:

public Controller()
{
   FXMLLoader loader = new FXMLLoader(getClass().getResource(fxml));
   loader.setController(this);
   Parent root = loader.load();
   Stage stage = new Stage();
   stage.setScene(new Scene(root));
   stage.show();
}
Run Code Online (Sandbox Code Playgroud)

这非常有效,因为现在我只需调用构造函数来创建新窗口。

但我不得不删除

fx:controller="package.Class"
Run Code Online (Sandbox Code Playgroud)

FXML 文件中的属性,因为否则当我调用时会抛出异常(“javafx.fxml.LoadException:控制器已设置”)

fxmlloader.setController(this);
Run Code Online (Sandbox Code Playgroud)

构造函数中的方法。由于我使用 NetBeans 及其“创建控制器”功能(右键单击 FXML 文件),因此由于缺少属性而无法创建控制器类。

概括:

我想要实现的是一种在 FXML(对于 NetBeans)中仍然设置“fx:controller”属性的方法,并且还能够在 Controller 类中方便地加载 FXML。

这是可能的,还是我需要某种创建 FXML 窗口的包装类?

提前致谢。

Jam*_*s_D 5

你可以这样做:

public Controller()
{
   FXMLLoader loader = new FXMLLoader(getClass().getResource(fxml));
   loader.setControllerFactory(type -> {
       if (type == Controller.class) {
           return this ;
       } else {
           try {
               return type.newInstance();
           } catch (RuntimeException e) {
               throw e ;
           } catch (Exception e) {
               throw new RuntimeException(e);
           }
       }
   });
   Parent root = loader.load();
   Stage stage = new Stage();
   stage.setScene(new Scene(root));
   stage.show();
}
Run Code Online (Sandbox Code Playgroud)

这将允许您(事实上,您需要)fx:controller在 FXML 文件中拥有该属性。基本上,它的作用是指定一个函数,FXMLLoader可以使用该函数从指定的类获取控制器实例。在这种情况下,如果 FXML 加载器正在查找该类的对象Controller,它将返回当前对象,否则仅创建指定类的新对象。

  • @Ignatiamus“FXMLLoader”将使用与“主”FXML 文件相同的控制器工厂来加载所包含的 FXML 文件。我更新了答案以提供解决此用例的代码。 (2认同)