Search code examples
user-interfacejavafxjavafx-8

JavaFx: Creating a text input box


I am working on a textEditor project and would like to create a TextInputDialog type window prompt that can accept input text from the TextArea (I want it to be TextArea instead of TextField) and return the input string. I also do have a button in the GUI I created. Pressing the button, the string in the TextArea must be returned and the gui window has to be closed.

    public String CommentWindow(String selectedText){
    Stage commentWindow = new Stage();
    VBox box = new VBox(20);
    TextArea commentbox = new TextArea();
    Label commentlabel = new Label("Enter the annotation for " + 
    selectedText + " :");
    Button addComment = new Button("Add annotation");
    box.getChildren().addAll(commentlabel,commentbox,addComment);
    commentWindow.setScene(new Scene(box,350,250));
    commentWindow.show();
    String comment = commentbox.getText();
    return comment;
}

The problem with the following code is, I don't know how to make sure the string in the TextArea is returned after the button is pressed and also the window needs to be closed. I'm fairly new to JavaFx so please excuse me for code style.

Here is the image of the GUI: Comment Window

EDIT 1: I don't want to use any Dialog or Alert features of JavaFx. I am basically trying to build something like that on my own. I just want the gui window I am building to return the string of text input in the text area and close the window after pressing the button. Can someone please suggest me how to write code for that?


Solution

  • You have several options for this, but I will present one of them. If you are only looking to have a TextArea in the TextInputDialog instead of a TextField, you could create your own class that provides that for you. By looking at the source code for TextInputDialog, you can see it is pretty basic.

    What I've done here is basically duplicate that class, while changing the TextField to a TextArea instead:

    TextFieldInputDialog.java

    import com.sun.javafx.scene.control.skin.resources.ControlResources;
    import javafx.application.Platform;
    import javafx.beans.NamedArg;
    import javafx.geometry.Pos;
    import javafx.scene.control.*;
    import javafx.scene.layout.GridPane;
    import javafx.scene.layout.Priority;
    
    /**
     * A dialog that shows a TextArea input
     */
    public class TextAreaInputDialog extends Dialog<String> {
    
        /**************************************************************************
         *
         * Fields
         *
         **************************************************************************/
    
        private final GridPane grid;
        private final TextArea textArea;
        private final String defaultValue;
    
        /**************************************************************************
         *
         * Constructors
         *
         **************************************************************************/
    
        /**
         * Creates a new TextInputDialog without a default value entered into the
         * dialog {@link TextField}.
         */
        public TextAreaInputDialog() {
            this("");
        }
    
        /**
         * Creates a new TextInputDialog with the default value entered into the
         * dialog {@link TextField}.
         */
        public TextAreaInputDialog(@NamedArg("defaultValue") String defaultValue) {
            final DialogPane dialogPane = getDialogPane();
    
            // -- textarea
            this.textArea = new TextArea(defaultValue);
            this.textArea.setMaxWidth(Double.MAX_VALUE);
            GridPane.setHgrow(textArea, Priority.ALWAYS);
            GridPane.setFillWidth(textArea, true);
    
            this.defaultValue = defaultValue;
    
            this.grid = new GridPane();
            this.grid.setHgap(10);
            this.grid.setMaxWidth(Double.MAX_VALUE);
            this.grid.setAlignment(Pos.CENTER_LEFT);
    
            dialogPane.contentTextProperty().addListener(o -> updateGrid());
    
            setTitle(ControlResources.getString("Dialog.confirm.title"));
            dialogPane.setHeaderText(ControlResources.getString("Dialog.confirm.header"));
            dialogPane.getStyleClass().add("text-input-dialog");
            dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
    
            updateGrid();
    
            setResultConverter((dialogButton) -> {
                ButtonBar.ButtonData data = dialogButton == null ? null : dialogButton.getButtonData();
                return data == ButtonBar.ButtonData.OK_DONE ? textArea.getText() : null;
            });
        }
    
        /**************************************************************************
         *
         * Public API
         *
         **************************************************************************/
    
        /**
         * Returns the {@link TextField} used within this dialog.
         */
        public final TextArea getEditor() {
            return textArea;
        }
    
        /**
         * Returns the default value that was specified in the constructor.
         */
        public final String getDefaultValue() {
            return defaultValue;
        }
    
        /**************************************************************************
         *
         * Private Implementation
         *
         **************************************************************************/
    
        private void updateGrid() {
            grid.getChildren().clear();
    
            grid.add(textArea, 1, 0);
            getDialogPane().setContent(grid);
    
            Platform.runLater(() -> textArea.requestFocus());
        }
    }
    

    Now, you can just drop that class into your project and use it like any other TextInputDialog.

    Here's a simple application that makes use of it:

    import javafx.application.Application;
    import javafx.geometry.Insets;
    import javafx.geometry.Pos;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.layout.VBox;
    import javafx.stage.Stage;
    
    import java.util.Optional;
    
    public class TextInputPopup extends Application {
    
        public static void main(String[] args) {
            launch(args);
        }
    
        @Override
        public void start(Stage primaryStage) {
    
            // Simple interface
            VBox root = new VBox(5);
            root.setPadding(new Insets(10));
            root.setAlignment(Pos.CENTER);
    
            // Create a button to launch the input window
            Button button = new Button("Get input");
            button.setOnAction(e -> {
    
                // Create the new dialog
                TextAreaInputDialog dialog = new TextAreaInputDialog();
                dialog.setHeaderText(null);
                dialog.setGraphic(null);
    
                // Show the dialog and capture the result.
                Optional result = dialog.showAndWait();
    
                // If the "Okay" button was clicked, the result will contain our String in the get() method
                if (result.isPresent()) {
                    System.out.println(result.get());
                }
    
            });
    
            root.getChildren().add(button);
    
            // Show the Stage
            primaryStage.setWidth(300);
            primaryStage.setHeight(300);
            primaryStage.setScene(new Scene(root));
            primaryStage.show();
        }
    }
    

    There is certainly room for further customization, but perhaps this will lead you in the right direction.