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 경로는 resources 폴더, 즉 classpath에 있는 fxml 폴더의 view.fxml 파일을 나타냅니다.

getClass().getResource() 호출은 런타임에 classloader 개체를 호출하여 전달된 리소스의 classpath를 검색합니다. 이러한 방식으로 fxml 폴더와 해당 폴더 내 view.fxml 파일을 찾습니다.

두 번째 이유는 일치하지 않는 구성 요소 ID가 있을 수 있습니다. 즉, 컨트롤러 파일에서 구성 요소 ID를 업데이트했지만 FXML 파일에서 해당 ID를 변경하는 것을 잊었을 수 있습니다(또는 그 반대의 경우도 마찬가지). 이 경우 Controllerview.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:controllerroot 요소의 컨트롤러를 지정하는 데 사용됩니다. FXML 문서당 하나의 컨트롤러를 가질 수 있으며 root 요소에 지정해야 합니다.

    이 코드에서 root 요소는 무엇입니까? AchnorPane 태그는 FXML 문서의 개체 그래프에서 최상위 개체인 이 코드 예제의 root 요소입니다.

    모든 UI 요소가 이 요소에 추가됩니다. 또한 컨트롤러가 충족해야 하는 규칙도 알아야 합니다. 이러한 규칙은 다음과 같습니다.

    • 컨트롤러는 FXML 로더에 의해 인스턴스화됩니다.
    • 컨트롤러에는 공개 no-args 생성자가 있어야 합니다. FXML 로더가 없으면 인스턴스화할 수 없으므로 로드 시 예외가 발생합니다.
    • 컨트롤러는 FXML의 이벤트 핸들러로도 지정할 수 있는 액세스 가능한 기능을 포함할 수 있습니다.
    • FXML 컨트롤러는 컨트롤러의 액세스 가능한 인스턴스 변수를 자동으로 찾습니다. 액세스 가능한 인스턴스 변수의 이름이 요소의 fx:id 속성과 일치하면 FXML의 개체 참조가 자동으로 컨트롤러 인스턴스 변수에 복사됩니다.

    이 기능은 FXML의 UI 요소 참조를 컨트롤러에서 액세스할 수 있도록 합니다. 그러면 컨트롤러에서 사용할 수 있습니다.

    • 컨트롤러는 인수를 허용하지 않고 void 유형을 반환해서는 안 되는 initialize() 함수에 액세스할 수도 있습니다. 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 파일을 로드하고 장면을 만들고 이 장면을 스테이지로 설정하고 해당 스테이지를 표시합니다.

OUTPUT(Button을 클릭할 때마다 IDE 콘솔에 CLICK 단어 인쇄):

JavaFX fxml 로드 예외에 대한 솔루션 - 출력

다음 스크린샷을 확인하여 각 파일을 올바른 위치에 배치하십시오.

JavaFX fxml 로드 예외에 대한 솔루션 - 파일 디렉토리

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