2016-01-14 2 views
45

Моего Application класса выглядит следующим образом:JavaFX FXML контроллер - конструктор против метода инициализации

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:controller), вызывая первый конструктор по умолчанию и то initialize метод:

public class MainViewController { 

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

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

выход:

first 
second 

Почему метод initialize существует? В чем разница между использованием конструктора или методом initialize для инициализации контроллера?

Спасибо за ваши предложения!

ответ

51

Метод 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. 
    } 
} 
62

В нескольких словах: Конструктор вызывается первым, то любые @FXML аннотированные поля заполняются, то initialize() называется. Таким образом, конструктор НЕ имеет доступа к полям @FXML, относящимся к компонентам, определенным в файле .fxml, тогда как initialize() имеет к ним доступ.

Цитирование от Introduction to FXML:

[...] контроллер может определить метод Initialize(), который будет вызываться один раз на исполнителя контроллера, когда содержание связанного с ним документа были полностью загружены [...] Это позволяет исполнительному классу выполнять любую необходимую пост-обработку содержимого.

+1

Я не понимаю. Как он это делает, над «FXMLLoader», правильно? Поэтому я не вижу преимущества в ожидании метода 'initialize()' -. Как только FXML загружается, следующий код имеет доступ к переменным '@ FXML'. Конечно, он делает это в методе start, а не в конструкторе, но будет ли 'initialize()' приносить какую-либо выгоду в его случае? – codepleb

Смежные вопросы