Get a notification in Swing when a thread completes / is finished - java

It seems I miss a certain point in Java and Swing. The issue is as follows:
I have a swing GUI with a Start / Stop button (And some more)
It starts the function (What is set up as a thread in this case), Thread starts, it works, Swing GUI is fully operational and does all the other things it is made for, e.g. modifying parameters for the worker thread.
Of course, sending an interrupt to ask the thread to stop on users request is in and functions. So far so good.
But I did not found a way that Swing GUI notices the thread stopped on its own:
If I ignore it, it confuses the user.
I of course put a loop in, where Swing GUI regularly asks if Thread.isAlive (And sleeps some time to ask again), but this loop completely blocks Swing GUI.
Ideally, I would like to get a notification or an event that the thread has stopped.
Just like all the other events, Swing processes:-) .
What is the proper way to set it up?

Have a look at the SwingWorker. It is designed to perform tasks on the background as the result of a Swing event such a button press. It has hooks to listen for when the task finishes.

use a boolean flag 'done' private field. initialize done=false; when your thread run() method is complete set done=true inside thread run() method.
monitoring the value of the flag 'done' will tell you when your thread has finished.

Related

Java GUI stuck when press a button [duplicate]

This may be a basic question but one that I am stuck on.
I would like some more understanding on why the GUI is blocked when I start a new thread(runnable) from a button click event? and how do I overcome that? What am I doing wrong?
The code below starts a new thread when it is clicked, however I would like to change the background color of a textbox when that button is clicked but I am unable to do that, also the main ui is unresponsive whilst that thread is running, I believed that I was implementing it correctly by starting a new thread so as to NOT block the main ui but I must have missed something out as this obviously not desired behaviour.
Code:
private void startButtonEvent(ActionEvent evt) {
ntmStatusText.setBackground(Color.green);// textbackground I want to change
//Start Ntm Thread
Thread thread = new Thread(new NtmThread());
thread.start();
while(thread.isAlive()){
System.out.println("thread still working");
}
System.out.println("thread stopped");
}
How do I stop my Ui from becoming unresponsive when running threads?
while(thread.isAlive()){ is a blocking method, it will stop the Event Dispatching Thread until Thread.isAlive becomes false, this prevents it from been able to process new events that are been added to the event queue, including paint requests
This occurs because Swing is a single threaded environment, meaning that there is a single thread responsible for process all events coming into the program. This is handled by the Event Dispatching Thread.
All user generated events are managed within the EDT (that is, you actionPerformed method, is called within the context of the EDT)
Concurrency in Swing
You eaither theen to provide a call back functionality to your NtmThread or consider using a SwingWorker and attaching a PropertyChanegListener to it a monitor for the property state and check that the SwingWorkers state has changed to DONE
See Worker Threads and SwingWorker for more details
As an example: How to use jProgress bar for ProcessBuilder process?
You have created a new thread but you are using current thread to check if the created thread is alive or not while(thread.isAlive()){.
So the current thread can never come out of the loop untill thread you created is not stopped.
And your this current thread was responsible for doing all gui work, but you made it stuck, that is why your GUI is blocked.

Does JFrame setVisibility(false) stop all threads I created?

When executing the command this.setVisible(false), does it stop all threads that are running specifically on that frame?
If not, is there an easy way to stop all of them automatically?
I think we have a conceptual problem here. There are no "threads running on a JFrame." There is one thread, the Event Dispatch Thread, that runs ALL Swing objects, frames, etc.
The EDT (Event Dispatch Thread) does not stop because you made one window invisible. However, if ALL Swing objects become unreachable (eligible for garbage collection) then the Swing EDT does shut down. (The app-note linked below says you can also call Window.dispose() on a frame to make it undisplayable; it then no longer counts for keeping the EDT running.)
The more precise conditions for shutting down the EDT are in this app-note:
Starting with 1.4, the behavior has changed as a result of the fix for
4030718. With the current implementation, AWT terminates all its helper
threads allowing the application to exit cleanly when the following
three conditions are true:
There are no displayable AWT or Swing components.
There are no native events in the native event queue.
There are no AWT events in java EventQueues.
Prior to Java 1.4, the EDT never shuts down. Hopefully you don't need to go that far back.
If you want to shutdown a group of threads, you have to do it manually (other than using some course method like System.exit()). I would look at Executors which enable you to manage threads fairly easily.
No, setting the JFrame visibility to false won't stop all threads you created with new Thread().
If not, is there an easy way to stop all of them automatically?
To stop all of them automatically there is no way (unless terminate all the program)
You need to have them stored in a list or a vector, for example, and then use the method Thread.interrupt()
Something like this:
for(Thread thread : threads) //where threads is a List
{
thread.interrupt();
}
No it does not!
The Thread does still run in background, but you cant interact with the Frame.
To Stop all threads you could do:
System.exit(1) which would terminate all Threads or for every Thread
Thread.sleep(10000000000); which would stop the Thread for a certain amount of time (in milliseconds).

Gui blocked when starting Thread from button clicked event

This may be a basic question but one that I am stuck on.
I would like some more understanding on why the GUI is blocked when I start a new thread(runnable) from a button click event? and how do I overcome that? What am I doing wrong?
The code below starts a new thread when it is clicked, however I would like to change the background color of a textbox when that button is clicked but I am unable to do that, also the main ui is unresponsive whilst that thread is running, I believed that I was implementing it correctly by starting a new thread so as to NOT block the main ui but I must have missed something out as this obviously not desired behaviour.
Code:
private void startButtonEvent(ActionEvent evt) {
ntmStatusText.setBackground(Color.green);// textbackground I want to change
//Start Ntm Thread
Thread thread = new Thread(new NtmThread());
thread.start();
while(thread.isAlive()){
System.out.println("thread still working");
}
System.out.println("thread stopped");
}
How do I stop my Ui from becoming unresponsive when running threads?
while(thread.isAlive()){ is a blocking method, it will stop the Event Dispatching Thread until Thread.isAlive becomes false, this prevents it from been able to process new events that are been added to the event queue, including paint requests
This occurs because Swing is a single threaded environment, meaning that there is a single thread responsible for process all events coming into the program. This is handled by the Event Dispatching Thread.
All user generated events are managed within the EDT (that is, you actionPerformed method, is called within the context of the EDT)
Concurrency in Swing
You eaither theen to provide a call back functionality to your NtmThread or consider using a SwingWorker and attaching a PropertyChanegListener to it a monitor for the property state and check that the SwingWorkers state has changed to DONE
See Worker Threads and SwingWorker for more details
As an example: How to use jProgress bar for ProcessBuilder process?
You have created a new thread but you are using current thread to check if the created thread is alive or not while(thread.isAlive()){.
So the current thread can never come out of the loop untill thread you created is not stopped.
And your this current thread was responsible for doing all gui work, but you made it stuck, that is why your GUI is blocked.

Thread output listener

I need to make a thread that start at swing button push and wait for input from rs232, process it and return String to my variable. The question is how to do that?
it should be something like that:
String myOutputString = waitForInputThread();
Or if its possible in swing panel make something like listener that do something if this waitForInputThread send interrupt (for example, if get rs232 input do update a list of items in JTable).
Could you give me some clues, tutorials, examples etc ?
To avoid blocking the Event Dispatch Thread (which is the thread that updates the GUI), start a new thread to interact with the RS232. The SwingWorker class is one option, but you can just as easily use a normal thread.1 Blocking the EDT causes your GUI to freeze, so it must never be used for lengthy tasks.
Once your result is computed, update the GUI using SwingUtilities.invokeLater(). This ensures the GUI change occurs on the EDT.
1 I tend to find normal threads executed via an ExecutorService are better for unit testing (as you can write an ExecutorService that immediately executes the Runnable, avoiding any nasty thread issues with JUnit).

EDT in Java, how does it work, does it behave like normal thread (single or mutli)?

this is a beginner question:
I am working on a small chat program that use TCP to deliver messages, and I have a simple GUI to display it, I have finished the program, but the EDT has confused me a lot...
does EDT behave like it "extends Thread"? I imagine it is a single thread since I will need worker thread to process the heavy logic, but apparently I can not do Thread.sleep/yield (I have a while loop that constantly reading message from the outputstream and append to the jTextArea, running in main Thread, I tried to terminate the while loop by set a false flag and then yield to main Thread, did not work.)
I am not so sure about how listener works, if I have to write it...I will probably start a thread for each listener, as soon as I hear something I will process it...but this is definitely wrong because it will make EDT a multithread ( a lot of ears ) but singlethread during the process ( only 1 brain )
This must be me lacking knowledge!! because in my head I just can not figure out how to fire an event... you pressed a button and java suddenly knows? I must missed something.
My first time post a question, hope it is clear
The Event Dispatching Thread is a Thread like any other Thread in Java.
It is responsible for dispatching all events and repaint requests (and few other things, like running synchronized Runnable). Any action you take that blocks the EDT will stop it from processing these events, making it look like your application has hung ... because basically it has.
All interactions with any UI component MUST be executed within the context of the EDT. That means you should never try and create or update any UI component from any Thread other then the EDT.
If you need to do any actions that are blocking or time consuming, you should use another thread. SwingWorker is an excellent place to start.
Adding listeners to component will not create more threads. The EDT will post event notifications back to the listeners (this is an incredibly shortened explanation, but the concept is sound), this is one of the reasons why you should never block the EDT.
How events are raised depends on the component. Mouse and keyboard events for example, will be posted to the Event Queue by a native portion of code dependent on the OS/implementation (as I understand it, coming from the ToolKit, but I could be wrong).
actionPerformed events raised by JButtons may be executed directly against the listener (not dispatched via the Event Queue), but within the EDT. This are raised by any number of events, but typically caused by mouse clicks and special key events. The JButton is notified of these because it registers itself with the Event Queue.
While getting an understanding of the workings is a good goal, you need to ask yourself, does it matter (in the short term)? Do you know how electricity gets from the light switch to the light? Or do you only care that it does?
Understand the rules required to use it (don't stick sharp objects into the power points) and let the understanding come as you become more confident.

Categories

Resources