JavaFX FXML 컨트롤러-생성자 대 초기화 방법


84

Application수업은 다음과 같습니다.

public class Test extends Application {

    private static Logger logger = LogManager.getRootLogger();

    @Override
    public void start(Stage primaryStage) throws Exception {

        String resourcePath = "/resources/fxml/MainView.fxml";
        URL location = getClass().getResource(resourcePath);
        FXMLLoader fxmlLoader = new FXMLLoader(location);

        Scene scene = new Scene(fxmlLoader.load(), 500, 500);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

는 먼저 기본 생성자를 호출 한 다음 메서드 를 호출 FXMLLoader하여 해당 컨트롤러의 인스턴스 ( FXML를 통해 파일에 제공됨)를 만듭니다 .fx:controllerinitialize

public class MainViewController {

    public MainViewController() {
        System.out.println("first");
    }

    @FXML
    public void initialize() {
        System.out.println("second");
    }
}

출력은 다음과 같습니다.

first
second

그렇다면 initialize방법이 존재 하는 이유는 무엇입니까? 생성자 또는 initialize컨트롤러를 초기화하는 방법을 사용하는 것의 차이점은 무엇입니까 ?

제안 해 주셔서 감사합니다!

답변:


124

간단히 말해서 : 생성자가 먼저 호출 된 다음 @FXML주석이 달린 필드가 채워진 다음 initialize()호출됩니다. 따라서 생성자는 @FXML.fxml 파일에 정의 된 구성 요소를 참조 하는 필드에 액세스 할 수 없지만 initialize()액세스 할 수 있습니다.

FXML 소개 에서 인용 :

[...] 컨트롤러는 initialize () 메서드를 정의 할 수 있습니다.이 메서드는 관련 문서의 내용이 완전히로드되었을 때 구현 컨트롤러에서 한 번 호출됩니다. [...]이를 통해 구현 클래스가 필요한 게시를 수행 할 수 있습니다. -콘텐츠 처리.


2
이해가 안 돼요. 그가하는 방식은 끝났 FXMLLoader죠? 그래서 나는 initialize()-메소드 를 기다리는 것의 이점을 보지 못합니다 . FXML이로드 되 자마자 다음 코드에서 @FXML변수에 액세스 할 수 있습니다. 물론, 그는 생성자가 아닌 시작 메서드에서 수행하지만 initialize()그의 경우에는 어떤 이점이 있습니까?
codepleb

90

initialize메서드는 @FXML주석이 달린 모든 멤버가 삽입 된 후에 호출 됩니다. 데이터로 채우려는 테이블 뷰가 있다고 가정합니다.

class MyController { 
    @FXML
    TableView<MyModel> tableView; 

    public MyController() {
        tableView.getItems().addAll(getDataFromSource()); // results in NullPointerException, as tableView is null at this point. 
    }

    @FXML
    public void initialize() {
        tableView.getItems().addAll(getDataFromSource()); // Perfectly Ok here, as FXMLLoader already populated all @FXML annotated members. 
    }
}

11

위의 답변 외에도 초기화를 구현하는 레거시 방법이 있다는 점에 유의해야합니다. fxml 라이브러리 에는 Initializable 이라는 인터페이스가 있습니다.

import javafx.fxml.Initializable;

class MyController implements Initializable {
    @FXML private TableView<MyModel> tableView;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        tableView.getItems().addAll(getDataFromSource());
    }
}

매개 변수 :

location - The location used to resolve relative paths for the root object, or null if the location is not known.
resources - The resources used to localize the root object, or null if the root object was not localized. 

그리고 문서의 간단한 사용 방법이 @FXML public void initialize()작동 하는 이유 :

NOTE이 인터페이스는 위치 및 리소스 속성을 컨트롤러에 자동으로 삽입하여 대체되었습니다. FXMLLoader는 이제 컨트롤러에 의해 정의 된 적절하게 주석이 달린 인수가없는 initialize () 메서드를 자동으로 호출합니다. 가능한 한 주입 방식을 사용하는 것이 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.