JavaFX FXML 載入異常的解決方法

Mehvish Ashiq 2023年10月12日
  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