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를 변경하는 것을 잊었을 수 있습니다(또는 그 반대의 경우도 마찬가지). 이 경우 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
태그에는 간단한 설명과 함께 아래에 나열된 다양한 속성이 있습니다.prefHeight
및prefWidth
속성을 사용하여 계산된 영역의 기본 높이 및 너비를 재정의할 수 있습니다.- FXML에서
fx:controller
는root
요소의 컨트롤러를 지정하는 데 사용됩니다. 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
단어 인쇄):
다음 스크린샷을 확인하여 각 파일을 올바른 위치에 배치하십시오.