• 0

Code doesn't seem to be running in order


Question

Hey all

I have some trouble with JavaFX and using the gui components. I basically have the following code

 

TextArea console;

 

console.appendText("stuff");

console.appendText("stuff");

console.appendText("stuff");

console.appendText("stuff");

console.appendText("stuff");

console.appendText("stuff");

console.appendText("Generating keys...");

//GENERATE RSA KEYS

console.appendText("Keys generated");

console.appendText("stuff");

 

It all shows up at one time. I feel that stuff should be appending before the Generating keys part.  I can change the size of the RSA key to test different speeds and all the appends occur after the key is created.

 

I also have a similar situation except I am trying to change the text of a button.

 

I have tried putting different segments of code in Runnables then into Threads but it doesn't make a difference. :(

 

Any ideas on how I can fix this?

Link to comment
Share on other sites

10 answers to this question

Recommended Posts

  • 0

You are probably doing all of this in whatever thread is performing the GUI drawing (which needs to return in order to update the UI). Runnable/Threads and such aren't going to work if you are just waiting for them to finish in the same thread where you are running the key generation from or if you are just stalling the GUI drawing thread. Even if the text append updates get scheduled in the latter case, if you are doing key generation in the GUI thread, how would the updates to the widget be displayed?

 

I found this snippet of code from stackoverflow that will probably work here to make this asynchronous if you drop your key generation and text appending code into it:

Platform.runLater(new Runnable(){
@Override
public void run() {
// Update your GUI here.
// Gen Key here?
}
});

--http://stackoverflow.com/questions/12860896/updating-the-javafx-gui-with-threads-and-or-tasks

 

As far as I can tell, you could also probably just drop all of your key generation code and GUI updates into a normal thread and run it.

 

*Note: I don't actually do JavaFX (let alone Java) programming, so if there are issues or my assumptions above are incorrect, please clarify.

Link to comment
Share on other sites

  • 0

The UI doesn't update when you modify a control, it updates after you modified a control and released the UI thread. So if you want to display "generating...", then generate the keys, then display the keys, the sequence needs to be:

 

 - append "generating..."

 - release the UI thread

 - generate the keys (preferrably on another thread than the UI thread to avoid making the UI non-responsive)

 - append "keys generated"

 - release the UI thread

 

Releasing the UI thread means returning from whatever event handler the UI has called you in. Basically the operation should look like:

void UIEventHandler() {
     display "generating"
     Dispatch to worker thread(GenerateKeys(KeysGeneratedCallback))
}

void KeysGeneratedCallback() {
     Dispatch to UI thread(display "keys generated")
}

This is of course pseudo-code, I have no idea exactly how to do this with JavaFX, but there certainly are some concurrency APIs in there. EDIT: you might want to look into http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm

Link to comment
Share on other sites

  • 0

You are probably doing all of this in whatever thread is performing the GUI drawing (which needs to return in order to update the UI). Runnable/Threads and such aren't going to work if you are just waiting for them to finish in the same thread where you are running the key generation from or if you are just stalling the GUI drawing thread. Even if the text append updates get scheduled in the latter case, if you are doing key generation in the GUI thread, how would the updates to the widget be displayed?

 

I found this snippet of code from stackoverflow that will probably work here to make this asynchronous if you drop your key generation and text appending code into it:

Platform.runLater(new Runnable(){
@Override
public void run() {
// Update your GUI here.
// Gen Key here?
}
});

--http://stackoverflow.com/questions/12860896/updating-the-javafx-gui-with-threads-and-or-tasks

 

As far as I can tell, you could also probably just drop all of your key generation code and GUI updates into a normal thread and run it.

 

*Note: I don't actually do JavaFX (let alone Java) programming, so if there are issues or my assumptions above are incorrect, please clarify.

 

Thanks for the code. I have used it before to update UI components. Putting the console append code in it doesn't change anything. Then if I also put the Key generating code into it, nothing happens, it just freezes.

The UI doesn't update when you modify a control, it updates after you modified a control and released the UI thread. So if you want to display "generating...", then generate the keys, then display the keys, the sequence needs to be:

 

 - append "generating..."

 - release the UI thread

 - generate the keys (preferrably on another thread than the UI thread to avoid making the UI non-responsive)

 - append "keys generated"

 - release the UI thread

 

Releasing the UI thread means returning from whatever event handler the UI has called you in. Basically the operation should look like:

void UIEventHandler() {
     display "generating"
     Dispatch to worker thread(GenerateKeys(KeysGeneratedCallback))
}

void KeysGeneratedCallback() {
     Dispatch to UI thread(display "keys generated")
}

This is of course pseudo-code, I have no idea exactly how to do this with JavaFX, but there certainly are some concurrency APIs in there. EDIT: you might want to look into http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm

Thanks for the info. I'll see what I can find.

Link to comment
Share on other sites

  • 0

^ Perhaps it is freezing because you aren't allowed to call methods that change the GUI outside of the GUI thread. In that case, you would have to do a callback as per what Andre is saying. 

Link to comment
Share on other sites

  • 0

^ Perhaps it is freezing because you aren't allowed to call methods that change the GUI outside of the GUI thread. In that case, you would have to do a callback as per what Andre is saying. 

To my knowledge, using the Platform.runLater should update the GUI on the GUI thread.

Appending text on the runLater should make the first sets of appends appear, then the Keys would generate, then the rest should append.

 

This is just the best of my current understanding.

Link to comment
Share on other sites

  • 0

To my knowledge, using the Platform.runLater should update the GUI on the GUI thread.

Appending text on the runLater should make the first sets of appends appear, then the Keys would generate, then the rest should append.

 

This is just the best of my current understanding.

That's what I thought also, but I do know that sometimes toolkits can be more restrictive than that. You should really try to discover why the freeze is occurring. To be honest, if there are restrictions I would expect it to throw an exception over just simply freezing.

Link to comment
Share on other sites

  • 0

To my knowledge, using the Platform.runLater should update the GUI on the GUI thread.

Appending text on the runLater should make the first sets of appends appear, then the Keys would generate, then the rest should append.

Platform.runLater dispatches to the UI thread. You can take my pseudo-code above and replace "Dispatch to UI thread" with Platform.runLater. Now you need to figure out how to dispatch to a worker thread.

Link to comment
Share on other sites

  • 0

^Ah I see now what the problem likely is. I didn't realize runLater() was scheduling explicitly on the GUI handling thread. I through the Application thread was separate and that calls to GUI updates would queue (regardless of the thread they were called in) to be handled by the GUI thread separately. Or to say this differently: I thought the main application and GUI threads were separate.

Link to comment
Share on other sites

  • 0

Okay I fixed it. When a button is clicked it runs a method which does all that appending and generating keys. I put that method call in its own thread and then the gui changes into the runLater and it works perfectly.

  • Like 1
Link to comment
Share on other sites

This topic is now closed to further replies.