Нужен ли @FXML для каждой декларации?

#java #javafx #fxml #scenebuilder

Вопрос:

Нужен ли @FXML для каждой декларации или только для первой?

Другими словами, должен ли я использовать

 @FXML
public Label timerLabel = new Label();
@FXML
public TextField mainTextField, projectTextField ;
@FXML
public Button goButton, deleteAllButton ;
@FXML
public ComboBox<String> projectComboBox ;
@FXML
public TableView<Entry> mainTable ;
@FXML
public TableColumn<Entry, String> titleColumn, timeColumn, dateColumn ;
@FXML
public TableColumn<Entry, Boolean> checkColumn, buttonColumn ;
@FXML
public checkBox checkAllCheckBox ;
 

Или

 @FXML
public Label timerLabel = new Label();
public TextField mainTextField, projectTextField ;
public Button goButton, deleteAllButton ;
public ComboBox<String> projectComboBox ;
public TableView<Entry> mainTable ;
public TableColumn<Entry, String> titleColumn, timeColumn, dateColumn ;
public TableColumn<Entry, Boolean> checkColumn, buttonColumn ;
public checkBox checkAllCheckBox ;
 

Спасибо!

Комментарии:

1. Попробуйте их обоих 😉

2. @Romeo Просто хочу отметить, что ваше заявление public Label timerLabel = new Label(); с комментариями @FXML неверно. Ссылки с аннотациями @FXML инициализируются во время загрузки fxml и не должны инициализироваться извне.

3. Что вы подразумеваете под «инициализировать метку времени»? Вы никогда не должны писать timerLabel = new TimerLabel() , если определение ссылки на метку времени было аннотировано @FXML .

4. На самом деле вам не нужны никакие @FXML аннотации, если ваши поля таковы public . Конечно, вы все равно никогда не должны создавать эти поля public ; вы должны их private создавать , и в этом случае требуются все @FXML аннотации. Но с кодом, как он есть, пропуск аннотаций не будет иметь никакого значения.

5. Я думаю, что пришло время FXMLLoader зарегистрировать ошибку или предупредить, если поле с комментариями @FXML уже создано во время загрузки. Или используйте экземпляр, как в setController().

Ответ №1:

@FXML Аннотация позволяет FXMLLoader вводить значения, определенные в файле FXML, в ссылки в классе контроллера. Другими словами, если вы аннотируете свой timerLabel с @FXML , то он будет инициализирован, FXMLLoader когда load() метод вызывается элементом в файле FXML с. fx:id="timerLabel" Как отмечали другие в комментариях, это означает, что вы никогда не должны писать такой код, как

 @FXML
private Label timerLabel = new Label();
 

Здесь timerLabel сначала будет инициализировано new Label(); значение, созданное вами в коде, а затем почти сразу же будет повторно инициализировано значение, определенное в файле FXML. Это в лучшем случае излишне, а в худшем-вводит в заблуждение. Если вы неправильно сопоставите имена переменных fx:id , ваша переменная будет ссылаться на неправильную Label , и ошибку будет очень трудно отследить.

Чтобы перейти к вашему актуальному вопросу:

Когда FXMLLoader файл FXML загружается, он попытается ввести в контроллер любые элементы, имеющие fx:id атрибут. Он будет искать

  1. Любое public поле с именем переменной, соответствующим fx:id атрибуту, или
  2. Любое поле ( public или нет) с именем переменной, соответствующим fx:id атрибуту, который аннотирован @FXML .

Таким образом, в вашем примере , поскольку все ваши поля есть public , вы можете опустить все @FXML аннотации (даже первые), и это все равно будет работать.

Однако, если вы будете следовать надлежащей практике и создадите свои поля private , то каждое объявление должно быть аннотировано @FXML , чтобы инъекция работала.

Так

 @FXML
private Label timerLabel;
@FXML
private TextField mainTextField;
 

и т. Д. Будет работать, но

 @FXML
private Label timerLabel;
private TextField mainTextField;
 

не будет.

Комментарии:

1. Требуется ли инъекция? Есть ли способ просто запросить у загрузчика интересующий меня элемент управления (по fx:id)?

2. Не уверен, что понимаю этот вопрос. Разве не это именно то, что делает инъекция?

Ответ №2:

для каждого

 fx:id="somename"
 

тебе нужна

 @FXML
public SomeClass somename;
 

Я предпочитаю писать это в одной строке, потому что ее легче читать, когда их много

 @FXML public SomeClass somename;
 

без инициализации

 @FXML
public Label timerLabel = new Label(); // this is wrong
 

Комментарии:

1. не timerLabel = new Label(); будет отменен ан FXMLLoader ?

2. Этот ответ вводит в заблуждение, поскольку @FXML он не нужен, когда поле открыто. Так public SomeClass somename; что без @FXML тоже работает, но вам это нужно somename , например, когда это не public так @FXML private SomeClass somename; .

Ответ №3:

 @FXML
private TextField idTextField;

@FXML
private TextField passwordTextField;
 

или

 @FXML
private TextField idTextField, passwordTextField;