Search code examples
javajavafxjava-8textfieldsettext

JavaFX can't settext() on Final TextField


I'm unable to set TextField if variable TextField is set as final but if i change it to private or public it changes text of my textfiel. I thought that final just don't allow create another instance of class. I tried print HashCode of both private and final TextField but they was not changing. So im curious why i have to have private or public TextField to SetText() to it.

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());
    }
}

Thank's you for answers.


Solution

  • When an FXMLLoader loads an FXML file, it

    1. Creates an instance of the controller class specified by fx:controller
    2. Creates instances of the classes described by the elements in the FXML file (i.e. for <Button> it creates a Button instance, etc), and sets their properties
    3. For elements with a fx:id attributes, sets the corresponding @FXML-injected field in the controller instance that was created
    4. Registers event handlers, etc.
    5. Calls the initialize() method on the controller

    Since the @FXML fields are set after the constructor call has completed, they cannot be final. Additionally, it doesn't make sense to initialize them since they are going to be set by the FXMLLoader anyway: you should never initialize @FXML-annotated fields.

    So your field declarations should be

    @FXML
    TextField textfieldSelectedDirectory ;
    

    etc, (and you can, and probably should, make these private too).

    The final keyword simply means that the variable is assigned a value exactly once. While this is technically true in the set up I describe (the field is only ever assigned a value once, by the FXMLLoader), the compiler needs to know this in order for the code to compile, and since it cannot possibly know what the FXMLLoader is going to do with instances of your controller class, you cannot make these fields final.