JavaFX FXML 加载异常的解决方法

Mehvish Ashiq 2024年2月15日
  1. 导致 JavaFX FXML 加载异常的原因
  2. JavaFX FXML 加载异常的解决方法
JavaFX FXML 加载异常的解决方法

本教程介绍导致 JavaFX FXML 加载异常的原因并提供快速解决方案。

导致 JavaFX FXML 加载异常的原因

获得 JavaFX FXML 加载异常的第一个原因是 FXML 文件的路径未正确指定给加载程序。路径 /fxml/view.fxml 指的是一个名为 fxml 的文件夹中的文件 view.fxml,该文件夹位于 resources 文件夹中,即在 classpath 上。

getClass().getResource() 调用在运行时调用对象 classloader,它在 classpath 中搜索传递给它的资源。这样,它将在该文件夹中找到 fxml 文件夹和 view.fxml 文件。

第二个原因可能是组件 ID 不匹配,这意味着我们可能已经更新了 Controller 文件中的组件 ID,但忘记在 FXML 文件中更改该 ID(反之亦然)。在这种情况下,Controller 将无法在 view.fxml 文件中链接该组件。

看下面的块有一个清晰的理解。

控制器文件上:

@FXML
Button btnName1

FXML 视图 文件中:

fx:id="btnName_1"

以下是这两个原因的解决方案。

JavaFX FXML 加载异常的解决方法

要运行此应用程序,我们使用 Java 18、JavaFX 13 和 NetBeans IDE 版本 13。你可以根据自己的选择使用所有这些。

示例代码(view.fxml 文件,视图文件):

<!--Step1: XML declaration-->
<?xml version="1.0" encoding="UTF-8"?>

<!--Step 2: import necessary java types in FXML-->

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>

<!--Step 3: specify the FXML namespace-->

<AnchorPane prefHeight="300.0" prefWidth="400.0"
xmlns="http://javafx.com/javafx/11.0.1"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.mycompany.javafx_fxml_loadexception.viewController">

    <!--Step 4: layout pane have children-->
    <children>
        <Button fx:id="btTest" layoutX="170.0"
        layoutY="208.0" mnemonicParsing="false"
        onAction="#onBtTestAction" text="Button" />

        <Label layoutX="167.0" layoutY="126.0" text="Cick here!" />
   </children>

</AnchorPane>

以下是上述代码的分步说明。

  • 我们通过描述版本和编码来编写 XML 声明。
  • 在 FXML 中导入所有必需的 Java 类型。
  • 我们使用 AnchorPane 标签来声明 fx 命名空间前缀。此标签允许将子节点的边缘锚定到距锚窗格边缘的偏移量。

    如果锚窗格中有填充或边框,则将从这些插图的内边缘测量偏移量。AnchorPane 标签具有下面列出的各种属性,并附有简要说明。

    • prefHeightprefWidth 属性可用于覆盖区域计算的首选高度和宽度。
    • 在 FXML 中,fx:controller 用于在 root 元素上指定控制器。请记住,我们允许每个 FXML 文档有一个控制器,并且必须在 root 元素上指定。

    这段代码中的 root 元素是什么?AchnorPane 标记是此代码示例的 root 元素,它是 FXML 文档的对象图中的顶级对象。

    所有 UI 元素都将添加到此元素中。此外,我们还需要知道控制器必须满足的规则;这些规则如下:

    • 控制器由 FXML 加载器实例化。
    • 控制器必须具有公共 no-args 构造函数。FXML 加载器如果不存在,将无法实例化它,从而导致加载时出现异常。
    • 控制器可以包含可访问的函数,这些函数也可以在 FXML 中指定为事件处理程序。
    • FXML 控制器自动查找控制器的可访问实例变量。如果可访问实例变量的名称与元素的 fx:id 属性匹配,则来自 FXML 的对象引用将自动复制到控制器实例变量中。

    此功能将使控制器可以访问 FXML 中的 UI 元素引用。然后,控制器将能够使用它们。

    • 控制器还可以访问 initialize() 函数,该函数不能接受参数并返回 void 类型。一旦 FXML 文档的加载过程完成,FXML 加载器将调用 initialize() 函数。
  • 在 FXML 中,布局窗格包含子元素作为它们的子元素。考虑到项目需求,我们可以添加标签、按钮和其他元素。

示例代码(viewController.java 类,控制器类):

// Step 1: replace this package name with your package name
package com.mycompany.javafx_fxml_loadexception;

// Step 2: import necessary libraries
import javafx.fxml.FXML;
import javafx.scene.control.Button;

// Step 3: viewController class
public class viewController {
  // define button
  @FXML private Button btTest;

  // define the action when the button is clicked
  @FXML
  public void onBtTestAction() {
    System.out.println("CLICK");
  } // end onBtTestAction method

} // end viewController class

viewController.java 类是一个控制器类,它在某些成员上使用 @FXML 注释。请记住,此注解可用于构造函数和类。

使用此注释,我们指定 FXML 加载器可以轻松访问此成员,即使该成员是 private。如果 FXML 加载器使用 public 成员,我们不需要使用 @FXML 注释。

但是,对 public 成员使用 @FXML 不会引发任何错误。因此,最好对每个成员进行注释。

以下 FXML 将控制器类的 onBtTestAction() 函数设置为 Button 的事件处理程序:

<Button fx:id="btTest" layoutX="170.0" layoutY="208.0" mnemonicParsing="false"         onAction="#onBtTestAction" text="Button" />

示例代码(App.java 类,主类):

// Step 1: replace the package name with your package name
package com.mycompany.javafx_fxml_loadexception;

// Step 2: import necessary libraries
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

// Step 3: primary launch class extending the Application class
public class App extends Application {
  /**
   *
   * @param stage
   */
  @Override
  public void start(Stage stage) {
    // load the view.fxml file, add it to the scene and show it
    try {
      Parent parent = FXMLLoader.load(getClass().getResource("/fxml/view.fxml"));
      // create a scene
      Scene scene = new Scene(parent);
      // set scene to a stage
      stage.setScene(scene);
      // show the stage
      stage.show();
    } // end try
    catch (IOException e) {
      e.printStackTrace();
    } // end catch
  } // end start method

  public static void main(String[] args) {
    launch(args);
  } // end main method

} // end App class

主文件扩展Application 类并覆盖了它的抽象方法 start()。在 start() 方法中,我们加载 view.fxml 文件,创建场景,将此场景设置为舞台,并显示该舞台。

输出(当我们点击按钮时,在 IDE 的控制台上打印单词 CLICK):

JavaFX fxml 加载异常的解决方案 - 输出

检查以下屏幕截图以将每个文件放置在正确的位置:

JavaFX fxml 加载异常的解决方法 - 文件目录

作者: Mehvish Ashiq
Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook

相关文章 - Java JavaFX