Pratik Anand
Pratik Anand

Reputation: 805

How to multithread my existing javafx application

I am creating a javafx app. It uses some heavy programming (heavy mapping). I need to multithread it because the user-experience becomes laggy.
I don't want to re-write the whole code if it can be possible. But it is not necessary. I need someone to completely explain the life-cycle, how to control the thread and how to ask it to do something.
For instance, i provide a full list of mapping characters in my fxml controller:

@FXML
private static final Map <Character, String> myMap = new HashMap <> ();
static {
    myMap.put('a', "5");
    myMap.put('b', "6");
    myMap.put('c', "7");
    myMap.put('d', "8");
    //And so on...
}

Then i encode the input text on button press:

    String codedTextOut;                
    textToCode = enteredText.getText();
    StringBuilder encoderTextSB = new StringBuilder();
    for (char codeChar : textToCode.toCharArray()) {
        encoderTextSB.append(myMap.get(codeChar));
    }
    codedTextOut = encoderTextSB.toString();

It gives a laggy user experience. I want to create a separate thread to do the encoding action on button press. Please help and also explain the various properties of thread. (i have checked out http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm, but it is not much informative)

Upvotes: 3

Views: 2091

Answers (1)

Alexander Kirov
Alexander Kirov

Reputation: 3654

  1. Use predefined pool of threads, or new Thread(), where you provide runnable with your data.

it will move computations from javafx thread to some enother thread, so that user can continue interacting with the application.

  1. When result is ready, use runLater() - this call wil be done on javafx queue, so that you will not run into concurrency troubles.

This allows you to return results of evaluation to the UI. (you shouldn't interact with UI components from another thread).

Use another features from javafx concurrent package, like Task for instance, as an option.

Here is a code snippet :

@Override
public void start(Stage primaryStage) {
    final TextArea ta = new TextArea();
    ta.setMinSize(100, 100);
    Button btn = new Button();
    btn.setText("Encode'");
    btn.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {

            ta.setDisable(true);
            new Thread(new Runnable() {

                @Override
                public void run() {
                    final StringBuilder codedTextOut = new StringBuilder();
                    String textToCode = ta.getText();
                    StringBuilder encoderTextSB = new StringBuilder();
                    for (char codeChar : textToCode.toCharArray()) {
                        encoderTextSB.append(codeChar + 15);
                    }
                    codedTextOut.append(encoderTextSB);
                    Platform.runLater(new Runnable() {

                        @Override
                        public void run() {
                            ta.setText(codedTextOut.toString());
                            ta.setDisable(false);
                        }
                    });
                }
            }).start();
        }
    });

    VBox root = new VBox();
    root.getChildren().addAll(ta, btn);

    Scene scene = new Scene(root, 300, 250);

    primaryStage.setTitle("Encoder");
    primaryStage.setScene(scene);
    primaryStage.show();
}

On click on button, you disable a text area, create a new Thread, execute code in it, after that put runnable on javafx queue, and execute piece of code from the second runnable on JavaFX thread, where you assign new text and enable the text area back.

Upvotes: 2

Related Questions