JavaFX не может установить текст() в Final TextField

Я не могу установить TextField, если переменная TextField установлена ​​​​как окончательная, но если я изменю ее на частную или общедоступную, она изменит текст моего текстового поля. Я думал, что final просто не позволяет создать еще один экземпляр класса. Я попытался напечатать HashCode как частного, так и окончательного TextField, но они не менялись. Так что мне любопытно, почему у меня должен быть частный или общедоступный TextField для SetText().

public class SearchController {

    @FXML
    final TextField textfieldSelectedDirectory = new TextField();
    @FXML
    private Button path;
    @FXML
    private Label pathlabel;
    @FXML
    final TextField searchfield = new TextField();

    public String getSearchfield() {

        return searchfield.getText();
    }

    private MainApp mainApp;
    private Stage stage;

    public SearchController() {

    }

    @FXML
    private void Index() {

        IndexFiles.index();

    }

    @FXML
    private void search() {

        SearchFiles().Search();
        System.out.println(searchfield.hashCode());

        System.out.println("Somtu");

        System.out.println(getSearchfield());

    }

    private void setPath(File selectedDirectory) {
        String dir = selectedDirectory.getAbsolutePath();


        pathlabel.setText(dir);

        textfieldSelectedDirectory.clear();

        // textfieldSelectedDirectory.getParent().layout();

        System.out.println(textfieldSelectedDirectory.getText());
    }
}

Вам спасибо за ответы.


person Kristián Klostermann    schedule 24.03.2016    source источник


Ответы (2)


Когда FXMLLoader загружает файл FXML, он

  1. Создает экземпляр класса контроллера, указанного fx:controller
  2. Создает экземпляры классов, описанных элементами в файле FXML (т. е. для <Button> создает экземпляр Button и т. д.), и устанавливает их свойства
  3. Для элементов с атрибутами fx:id задает соответствующее введенное поле @FXML в созданном экземпляре контроллера.
  4. Регистрирует обработчики событий и т. д.
  5. Вызывает метод initialize() на контроллере

Поскольку поля @FXML устанавливаются после завершения вызова конструктора, они не могут быть final. Кроме того, нет смысла их инициализировать, так как они все равно будут установлены FXMLLoader: вам не следует никогда инициализировать @FXML-аннотированные поля.

Таким образом, ваши объявления полей должны быть

@FXML
TextField textfieldSelectedDirectory ;

и т. д. (и вы можете и, вероятно, должны сделать эти private тоже).

Ключевое слово final просто означает, что переменной присваивается значение ровно один раз. Хотя технически это верно в описываемой мной настройке (полю присваивается значение только один раз, FXMLLoader), компилятору необходимо знать это для того, чтобы код компилировался, и поскольку он не может знать, что FXMLLoader будет делать с экземплярами вашего класса контроллера, вы не можете сделать эти поля final.

person James_D    schedule 24.03.2016
comment
Большое спасибо. Компилятор позволил мне запустить его, единственное, что не работало, это SetText() или setPromptText(), но я смог получить значение, если написал что-то в TextField. У меня теперь все ясно, спасибо еще раз. Но мне все еще любопытно, почему компилятор позволил мне запустить его? - person Kristián Klostermann; 24.03.2016
comment
Ваш код компилируется, потому что он следует всем обычным правилам: у вас есть final полей, и им присваиваются значения ровно один раз. FXMLLoader попытается присвоить новые значения этим полям с помощью отражения (поэтому нет проверок компилятора) и потерпит неудачу (я удивлен, что нет трассировки стека или, по крайней мере, предупреждения), поэтому поля не переназначаются. Поэтому, когда вы вызываете setText(..), вы вызываете его в начальном текстовом поле, которое вы установили в инициализаторе контроллера, а не в том, которое вы указали в FXML (т.е. не в том, которое отображается). - person James_D; 24.03.2016

Вы не можете использовать переменные final в сочетании с внедрением FXML. С FXML поля будут созданы после вызова конструктора. Таким образом, вам придется удалить инициализацию new TextField(). Однако компилятор не позволит вам.

person Moh-Aw    schedule 24.03.2016