5

I am using Java FX textarea and using it as to provide information for the steps going on.

Steps are as follows. Copy a file. Delete old file. Copy New File. and then copy some properties from old to new file.

This whole step starts when a button is clicked.

The problem I am facing is that text area is not being updated as soon as I use the append command.

The append command adds data and when the function terminates, I get all the text together. I want the text area to be updated as I call the function.

In my program, the copy file operation, takes some time as it is a big file. So in the start I display message that the operation has started. and at the end of operation I want to display the operation has ended.

But the text area displays all these texts all together.

I read in oracle forum, that text area in FX uses a single thread hence wont display anything until the whole process is complete.

Article : https://community.oracle.com/message/9938117#9938117

Can any one suggest what should I do.?

New Edit

Okay on Button Click I am calling a function which executes the following methods.

  public void executeCmds(){

        createTempDirectory();
        copyConfigPropetiesFileValues();
        copyConfigProperties();
        copyYMLFile();
        copyYMLFileProperties();

        stopTomcatServer();

        deleteOldWar();
        copyNewWar();
        startTomcatServer();

        copyOldConfigFile();
        copyOldYMLFile();
 }

Now Each of the function is a process, which should be executed sequentially. And after each step is completed I want to update the GUI text area with a success message that this is complete.

For the I am using method as follows:

  public void createTempDirectory(){
         //Creating temporary directory for copying property files
         status_text_area.appendText("Trying to create a temp directory \n");
        File tempDir= new       File(tomcat_path.getText()+filePath.path_to_temp_directory);
         if(!tempDir.exists())
             tempDir.mkdirs();

    status_text_area.appendText("Created Temp directory to copy Config Files \n");

}

and same is with other functions. The copyWar file function and delete warfile function take time as it copies 130 MB file from a location to other.

So I want the textarea to be displayed as, 1. Started copying file and after some time

  1. FIle copied.

But the issue is , the text area does not populate at all, until all the functions are executed.

If I try to execute these via threads, then the order of execution is not guranteed. Please Help

Prateek Mishra
  • 1,226
  • 10
  • 21
  • 4
    Start with [*Concurrency in JavaFX*](https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm), for [example](http://stackoverflow.com/q/22772379/230513). – trashgod Apr 15 '16 at 05:23
  • 1
    A related example is seen [here](http://stackoverflow.com/a/27835238/230513). – trashgod Apr 15 '16 at 05:35

3 Answers3

8

Run your executeCmds() method in a background thread and update the text area using Platform.runLater():

public void executeCmds(){
    Thread thread = new Thread(() -> {
        createTempDirectory();
        copyConfigPropetiesFileValues();
        copyConfigProperties();
        copyYMLFile();
        copyYMLFileProperties();

        stopTomcatServer();

        deleteOldWar();
        copyNewWar();
        startTomcatServer();

        copyOldConfigFile();
        copyOldYMLFile();
    });
    thread.start();
}

and then

public void createTempDirectory(){
         //Creating temporary directory for copying property files
    updateStatus("Trying to create a temp directory \n");
    File tempDir= new File(tomcat_path.getText()+filePath.path_to_temp_directory);
    if(!tempDir.exists())
        tempDir.mkdirs();

    updateStatus("Created Temp directory to copy Config Files \n");
}

// similarly for other methods

private void updateStatus(String message) {
    if (Platform.isFxApplicationThread()) {
        status_text_area.appendText(message);
    } else {
        Platform.runLater(() -> status_text_area.appendText(message));
    }
}
James_D
  • 201,275
  • 16
  • 291
  • 322
0

Extending the approved response - if you need to wait for updated UI before you do anything else, use PlatformImpl.runAndWait(Runnable runnable)

Thread thread = new Thread(() -> {
    yourMethod();
    PlatformImpl.runAndWait(() -> {
        methodForUI();
    });
    methodAfterUIChanged();
});
thread.start();
Inkvii
  • 1
-3

Please can you give some code excerpt ?

I regulary make a similar mistake: concat returns the concatenate string and does not modify the string whose concat method is applied.

        String firstString = "txt";
        String resultString = firstString.concat(" next");

If your concern is really linked with thread, and if your code is close from the one you mention in the article, I suggest you copy data through a parrallel thread like javafx.application.Platform.runLater(e -> { // Do some long operation there }); Please refer to existing articles on Task and runlater: Platform.runLater and Task in JavaFX

Edit: as James_D mentionned, if the opeartion is really long you'd better use task. Read the article I linked to know more about the alternatives and their usage.

Community
  • 1
  • 1
AnthonyCFE
  • 71
  • 11
  • 1
    `Platform.runLater(...)` executes code on the FX Application Thread. You should ***never*** execute a long-running operation on the FX Application Thread. – James_D Apr 15 '16 at 11:36