当前位置: 首页 > 知识库问答 >
问题:

JavaFX-Application类可以是controller类吗

万俟财
2023-03-14

我目前正在自学JavaFX,我已经使用了一个简单的示例程序,它对视图进行了硬编码,并正在将其转化为一个使用FXML的程序(主要是为了让我能够使用SceneBuilder来构建UI)。我没有编写单独的controller类,而是使用application类(因此有1个Java文件和1个FXML文件)。我没有使用initialize()方法,因为它是一个线性流(显示UI、填充字段、等待输入)。弹出视图,但随后应用程序出错,因为没有任何控件映射到适当的变量(因此对于@fxml tableview<...>tabletablenull)。

但是,我放入了initialize()方法进行调试,在initialize()中注入控件,然后在initialize()退出时返回为null。

所以问题是,JavaFX是否将application类的新实例实例化为单独的控制器类?这就解释了变量超出范围的原因。或者是其他的东西(例如,控件仅在从JavaFX操作回调时才被注入)?

共有1个答案

闻人鸿飞
2023-03-14

FXMLLoader的默认行为是创建controller类的新实例并将该实例用作控制器。

具体而言,fxmlloader执行以下操作:

  • 读取根FXML元素。
    • 如果根FXML元素具有fx:controller属性,则
      • 如果控制器已经存在,则引发异常,否则创建指定类的实例1并将其设置为控制器

      是的,但这可能是个糟糕的主意。如果您只是使用fx:controllerapplication子类指定为控制器类,则会创建application子类的第二个实例,在该第二个实例上注入@fxml注释字段,并在该第二个实例上调用initialize()方法。显然,在调用start(...)的实例上,从未初始化@fxml-字段,也从未在该实例上调用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文件必须不具有fx:controller属性。

      这样做的问题是,你没有分离,没有灵活性。(例如,如果您在某个地方创建了FXML文件中定义的视图的第二个实例,则最终会得到第二个application子类实例,这充其量是违反直觉的(一个应用程序带有两个application实例……)。)

      所以我主张在基本上每种情况下都为控制器使用一个单独的类。application子类应该包含最少的代码,并且应该只用于启动应用程序。

      1这一步实际上稍微复杂一些。如果在fx:controller属性中指定了类,但不存在控制器,fxmlloader将检查是否有controllerFactory。如果存在一个,则将控制器设置为将指定的class传递给ControllerFactoryCall()方法的结果,否则将通过对指定类调用NewInstance()来创建(实际上是调用其无参数构造函数)。

 类似资料:
  • 我正在尝试编写使用SceneBuilder创建的按钮的功能。我在Scene builder中找到了“Code”部分,并设置了当我单击按钮时将启动的方法的名称(例如fileSelector)。在该方法中,我应该使用FileChooser变量(我需要从PC上获取一个图像并将其保存到一个“file”变量中)。 我复制了示例控制器骨架并将其粘贴到我的controller类中。现在我不知道如何实现该方法,因

  • 最近我正在用JavaFx2.0编程一个软件,但是我遇到了一个大问题,那就是——我如何访问一个控制器类?对于每个具有相同类类型的控制器类,它们可能会因为它所依赖的模型而表现不同,所以我想获取视图的控制器类并为其提供指定的模型,我可以这样做吗?我已经尝试通过FXMLLoader获取控制器,但是方法getController()返回null!为什么? 1.LightView.java 2.LightVi

  • 或 我在Mac和Windows机器上都尝试了这个,结果是一样的。 我猜程序找不到JavaFX。 我的JDK是jdk-11.0.11.9-hotspot 在我安装了JDK11之后,我以前的jdk8 javafx项目现在也不会运行了。 我尝试将maven中的所有javafx JAR添加到我的POM中,同样,我只能从NetBeans中运行它。 同样,来自JDK8和JDK11的应用程序在NetBeans中

  • 是否可以将“默认内容类型”设置为“application/json;v=2.0”。我说 default 是因为我使用的是 HttpClient 类,并且我使用 DefaultRequestHeaders 将我的代理设置为默认值。 我按照这个例子来创建我的头https://stackoverflow.com/a/10679340/196526,但是我也使用版本控制,关于版本控制的信息保存在内容类型中

  • 我有控制器方法,为此我正在创建Junit,但在调用服务方法时出现Null指针错误。我使用了电源模拟,但仍然得到Null指针。 方法: 测试方法: @InjectMocks私有DataSourceReportController dataSourceReportController; 在“dataSourceReportService.listDataSourceReportByCurrentRun

  • 但是使用此代码会出现冲突,因为我已经用FXML代码定义了项目中的控制器,要解决这一问题,删除FXML代码中的段就足够了,但是我不会这么做,因为将代码留在FXML中允许我访问SceneBuilder的一些好特性。