SwingWorker is an abstract class developed for the Swing library of the Java programming language. It is used to perform lengthy GUI interaction tasks in a background thread. While developing applications, sometimes the GUI hangs when it is trying to do some huge or lengthy task. This lag is a big bottleneck. For such purposes, SwingWorker is developed which schedules the execution of this lengthy task on a different thread while the GUI still remains responsive.
Java language has three threads, namely listed below as follows:
- Current Thread (Initial Thread): this is the thread on which the initial application logic executes.
- Event Dispatch Thread: all event handling code executes on this thread.
- Worker Threads: also known as background threads where all time-consuming background tasks are executed.
SwingWorker allows users to schedule the execution of background tasks on Worker Thread. But how will the user get to know when the task has finished its execution or if the user needs to update GUI(running on the initial thread) as per the thread execution? This implies we need inter-thread communication as well. SwingWorker is designed for such tricky situations that provide communication on the event dispatch thread.
Important Methods of SwingWorker
Method | Action Performed |
---|---|
cancel() | Attempts to cancel the execution of this task. This attempt will fail if the task has already been completed, has already been canceled, or could not be canceled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
After this method returns, subsequent calls to Future.isDone() will always return true. Subsequent calls to Future.isCancelled() will always return true if this method returned true. |
doInBackground() | Contains our logic of the background task i.e. what we want our thread to do. It runs on a worker thread and is necessary to implement. |
done() | It is called when the thread finished its execution. Also, any value returned by the doInBackground() function can be received inside this function using get(). Further, updates can be made to GUI inside this function. Thus, function executes on the Event Dispatch Thread after the doInBackground method is finished. |
execute() | Schedules this SwingWorker for execution on a worker thread. |
getProgress() | Returns the progress bound property. |
getState() | Returns the SwingWorker state-bound property. |
isCancelled() | Returns true if this task was canceled before it was completed normally. |
isDone() | Returns true if this task is completed. Completion may be due to normal termination, an exception, or cancellation — in all of these cases, this method will return true. |
get() | Waits if necessary for the computation to complete, and then retrieves its result. |
process() | Receives data chunks from the publish method asynchronously on the Event Dispatch Thread. Because this method is invoked asynchronously, publish() may have been called multiple times. |
publish() | It is to be used from inside the doInBackground method to deliver intermediate results for processing on the Event Dispatch Thread inside the process method. |
run() | Sets this Future to the result of computation unless it has been canceled. |
setProgress() | Sets the progress bound property. The value should be from 0 to 100. |
Implementation: SwingWorker
We want the thread to start execution when the button is clicked. See startThread() inside button’s action listener. The startThread function defines a new swingworker of the type javax.swing.SwingWorker where:
- T – the result type returned by this SwingWorker’s doInBackground and get methods, which is String in the below code.
- V – the type used for carrying out intermediate results by this SwingWorker’s publish and process methods, which is Integer in the below code.
Example
Java
// Java Program to Illustrate Working of SwingWorker Class // Importing required classes import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.List; import java.util.concurrent.ExecutionException; import javax.swing.*; // Main class // SwingWorkerSample public class GFG { private static JLabel statusLabel; private static JFrame mainFrame; // Method public static void swingWorkerSample() { mainFrame = new JFrame( "Swing Worker" ); mainFrame.setSize( 400 , 400 ); mainFrame.setLayout( new GridLayout( 2 , 1 )); mainFrame.addWindowListener( new WindowAdapter() { // Method @Override public void windowClosing(WindowEvent e) { System.exit( 0 ); } }); statusLabel = new JLabel( "Not Completed" , JLabel.CENTER); mainFrame.add(statusLabel); JButton btn = new JButton( "Start counter" ); btn.setPreferredSize( new Dimension( 5 , 5 )); btn.addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println( "Button clicked, thread started" ); startThread(); } }); mainFrame.add(btn); mainFrame.setVisible( true ); } // Method private static void startThread() { SwingWorker sw1 = new SwingWorker() { // Method @Override protected String doInBackground() throws Exception { // Defining what thread will do here for ( int i = 10 ; i >= 0 ; i--) { Thread.sleep( 100 ); System.out.println( "Value in thread : " + i); publish(i); } String res = "Finished Execution" ; return res; } // Method @Override protected void process(List chunks) { // define what the event dispatch thread // will do with the intermediate results // received while the thread is executing int val = chunks.get(chunks.size() - 1 ); statusLabel.setText(String.valueOf(val)); } // Method @Override protected void done() { // this method is called when the background // thread finishes execution try { String statusMsg = get(); System.out.println( "Inside done function" ); statusLabel.setText(statusMsg); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }; // Executes the swingworker on worker thread sw1.execute(); } // Main driver method public static void main(String[] args) { swingWorkerSample(); } } |
Output:
- Run the above code, click the button, and you’ll see a counter decrementing. Simultaneously do anything with the UI, it’ll still be responsive.
- List chunks are the parameter of the process() function and contain the list of every result published by the thread till this time of datatype Integer. The datatype Integer should match with our swingworker declaration.
This article is contributed by Ekta Goel. If you like Lazyroar and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the Lazyroar main page and help other Geeks. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.