mrfsl
mrfsl

Reputation: 65

Updating TextField - JavaFx

I have 1 "ViewElements"-Class, 1 Controller and 1 FXML-file.

The ViewElements-Class contains the elements of the FXML like Buttons and textfields. The Controller-Class contains the Business logic.

I try to update the TextField "textfieldDateiAuswaehlen", I want to set the path of the File into the TextField but my method does not work.

ViewElements:

public class ViewElements {

@FXML private TextField textfieldDateiAuswaehlen;
@FXML private TextArea textareaXmlContent;
@FXML private Button buttonXmlBearbeiten;
@FXML private Button buttonXmlLaden;
@FXML private Button buttonXmlOeffnen;

public ViewElements() {
    this.textfieldDateiAuswaehlen= new TextField();
    this.textareaXmlContent = new TextArea();
    this.buttonXmlBearbeiten = new Button();
    this.buttonXmlLaden = new Button();
    this.buttonXmlOeffnen = new Button();
}

public TextField getTextfieldDateiAuswaehlen() {
    return textfieldDateiAuswaehlen;
}

public void setTextfieldDateiAuswaehlenText(String text) {
    this.textfieldDateiAuswaehlen.setText(text);

}

public String getTextfieldDateiAuswaehlenContent() {
    return this.textfieldDateiAuswaehlen.getText();
}

public TextArea getTextareaXmlContent() {
    return textareaXmlContent;
}

public void setTextareaXmlText(String text) {
    this.textareaXmlContent.setText(text);
}

public Button getButtonXmlBearbeiten() {
    return buttonXmlBearbeiten;
}


public Button getButtonXmlLaden() {
    return buttonXmlLaden;
}

public Button getButtonXmlOeffnen() {
    return buttonXmlOeffnen;
}}

Controller:

public class SampleController implements Initializable{

ViewElements viewElems= new ViewElements();


@FXML
private void handleButtonLaden(ActionEvent event){
    System.out.println("Klicked");
}

@FXML
private void handleButtonXmlOeffnen(ActionEvent event){

    FileChooser filechooser = new FileChooser();

    File file = filechooser.showOpenDialog(null);

    //Falls eine Datei ausgewaehlt ist
    if(file != null){

        //Falls TextField leer ist
        if(viewElems.getTextfieldDateiAuswaehlenContent().isEmpty()) {

            System.out.println(file.getAbsolutePath().toString());

            viewElems.getTextfieldDateiAuswaehlen().clear();

            String verzeichnis = file.getAbsolutePath().toString();

            viewElems.setTextfieldDateiAuswaehlenText(verzeichnis);


            Service<Void> service = new Service<Void>() {
                @Override
                protected Task<Void> createTask() {
                    return new Task<Void>() {
                        @Override
                        protected Void call() throws Exception {
                            Platform.runLater(() -> viewElems.setTextfieldDateiAuswaehlenText(verzeichnis));
                            return null;
                        }
                    };
                }
            };
            service.start();

            System.out.println("PRINT: " + viewElems.getTextfieldDateiAuswaehlenContent());
        }
    }

}

@Override
public void initialize(URL location, ResourceBundle resources) {
}}

enter image description here

In the screenshot you see that the path is passed to TextField but the TextField in the UI does not update.

Where is my mistake?

Upvotes: 0

Views: 3592

Answers (1)

James_D
James_D

Reputation: 209339

When you load the FXML file the FXMLLoader creates the UI nodes corresponding to the elements in the FXML.

If you declare a controller, give the elements fx:id attributes, and declare @FXML-annotated fields in the controller, the FXMLLoader will set those fields in the controller to the UI nodes created from the FXML.

In your code, your controller contains no @FXML-annotated fields. You create an instance of your ViewElements class, which creates some new instances of TextField and Button:

public ViewElements() {
    this.textfieldDateiAuswaehlen= new TextField();
    this.textareaXmlContent = new TextArea();
    this.buttonXmlBearbeiten = new Button();
    this.buttonXmlLaden = new Button();
    this.buttonXmlOeffnen = new Button();
}

Obviously these are not the same text fields and buttons created by the FXMLLoader.

Presumably, somewhere, you load the FXML and display the UI created by the FXMLLoader; but you don't display the UI nodes created in your ViewElements instance. So when you modify the nodes in your ViewElements instance, you are not modifying the UI you have displayed, and consequently you don't see anything.

You need to place the UI elements directly in the controller (which is perhaps better thought of as a presenter). The only way the FXMLLoader can assign the objects it creates to fields is if those fields are in the controller, because that is the only other object the controller "knows about".

If you want to separate the logic into a different class from the class that contains the UI elements, then make the "controller" the class that has the UI elements, and create a different class containing the implementation of the logic. Then in the "controller" class, just delegate the user event handling to your new class.

I.e. change the fx:controller attribute to point to ViewElements, and refactor as

public class ViewElements {

    @FXML private TextField textfieldDateiAuswaehlen;
    @FXML private TextArea textareaXmlContent;
    @FXML private Button buttonXmlBearbeiten;
    @FXML private Button buttonXmlLaden;
    @FXML private Button buttonXmlOeffnen;

    private SampleController controller ;

    public void initialize() {
        controller = new SampleController(this);
    }

    @FXML
    private void handleButtonXmlOeffnen(ActionEvent event){
        controller.handleButtonXmlOeffnen();
    }

    public TextField getTextfieldDateiAuswaehlen() {
        return textfieldDateiAuswaehlen;
    }

    public void setTextfieldDateiAuswaehlenText(String text) {
        this.textfieldDateiAuswaehlen.setText(text);

    }

    public String getTextfieldDateiAuswaehlenContent() {
        return this.textfieldDateiAuswaehlen.getText();
    }

    public TextArea getTextareaXmlContent() {
        return textareaXmlContent;
    }

    public void setTextareaXmlText(String text) {
        this.textareaXmlContent.setText(text);
    }

    public Button getButtonXmlBearbeiten() {
        return buttonXmlBearbeiten;
    }


    public Button getButtonXmlLaden() {
        return buttonXmlLaden;
    }

    public Button getButtonXmlOeffnen() {
        return buttonXmlOeffnen;
    }

}
public class SampleController {

    private final ViewElements viewElems ;

    public SampleController(ViewElements viewElems) {
        this.viewElems = viewElems ;
    }



    public void handleButtonXmlOeffnen() {

        FileChooser filechooser = new FileChooser();

        File file = filechooser.showOpenDialog(null);

        //Falls eine Datei ausgewaehlt ist
        if(file != null){

            //Falls TextField leer ist
            if(viewElems.getTextfieldDateiAuswaehlenContent().isEmpty()) {

                System.out.println(file.getAbsolutePath().toString());

                viewElems.getTextfieldDateiAuswaehlen().clear();

                String verzeichnis = file.getAbsolutePath().toString();

                viewElems.setTextfieldDateiAuswaehlenText(verzeichnis);


                Service<Void> service = new Service<Void>() {
                    @Override
                    protected Task<Void> createTask() {
                        return new Task<Void>() {
                            @Override
                            protected Void call() throws Exception {
                                Platform.runLater(() -> viewElems.setTextfieldDateiAuswaehlenText(verzeichnis));
                                return null;
                            }
                        };
                    }
                };
                service.start();

                System.out.println("PRINT: " + viewElems.getTextfieldDateiAuswaehlenContent());
            }
        }

    }



}

Upvotes: 2

Related Questions