I have a message label and a submit button. The submit button will be pressed multiple times, and the action for the each press can take up to a minute.

When the button is pressed, I want to set the message to empty, and after the task is complete, I want to set the message to "Complete".

private void submitActionPerformed(java.awt.event.ActionEvent evt) {
   message = "";
   updateMessageLabel();

   doTheTask();

   /* this update is apply to the label after completion */
   message = "Complete";
}

Is it possible to update that message label before the submitActionPerformed() method is run (or in the method), but after the the button is clicked?


Although the Swing concurrency tutorial already contains some very good samples on how to deal with concurrency in Swing, find below an example which

  • contains a checkbox to prove the UI is still alive
  • has a progress bar, which gets updated from the SwingWorker
  • has a label, which gets updated once the SwingWorker is finished

    import javax.swing.JCheckBox;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JProgressBar;
    import javax.swing.SwingWorker;
    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import java.lang.reflect.InvocationTargetException;
    import java.util.List;
    import java.util.concurrent.ExecutionException;
    
    public class SwingWorkerExample {
      private static JProgressBar PROGRESS_BAR;
      private static JLabel OUTPUT_LABEL;
      private static JFrame createGUI(){
        JFrame testFrame = new JFrame( "TestFrame" );
    
        PROGRESS_BAR = new JProgressBar(  );
        PROGRESS_BAR.setMinimum( 0 );
        PROGRESS_BAR.setMaximum( 100 );
    
        OUTPUT_LABEL = new JLabel( "Processing" );
    
        testFrame.getContentPane().add( PROGRESS_BAR, BorderLayout.CENTER );
        testFrame.getContentPane().add( OUTPUT_LABEL, BorderLayout.SOUTH );
    
        //add a checkbox as well to proof the UI is still responsive
        testFrame.getContentPane().add( new JCheckBox( "Click me to proof UI is responsive" ), BorderLayout.NORTH );
    
    
    
        testFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        return testFrame;
      }
    
      public static void main( String[] args ) throws InvocationTargetException, InterruptedException {
        EventQueue.invokeAndWait( new Runnable() {
          @Override
          public void run() {
            JFrame frame = createGUI();
    
            frame.pack();
            frame.setVisible( true );
          }
        } );
        //start the SwingWorker outside the EDT
        MySwingWorker worker = new MySwingWorker( PROGRESS_BAR, OUTPUT_LABEL );
        worker.execute();
      }
      private static class MySwingWorker extends SwingWorker<String, Double>{
        private final JProgressBar fProgressBar;
        private final JLabel fLabel;
        private MySwingWorker( JProgressBar aProgressBar, JLabel aLabel ) {
          fProgressBar = aProgressBar;
          fLabel = aLabel;
        }
    
        @Override
        protected String doInBackground() throws Exception {
          int maxNumber = 10;
          for( int i = 0; i < maxNumber; i++ ){
            Thread.sleep( 2000 );//simulate long running process
            double factor = ((double)(i+1) / maxNumber);
            System.out.println("Intermediate results ready");
            publish( factor );//publish the progress
          }
          return "Finished";
        }
    
        @Override
        protected void process( List<Double> aDoubles ) {
          //update the percentage of the progress bar that is done
          int amount = fProgressBar.getMaximum() - fProgressBar.getMinimum();
          fProgressBar.setValue( ( int ) (fProgressBar.getMinimum() + ( amount * aDoubles.get( aDoubles.size() - 1 ))) );
        }
    
        @Override
        protected void done() {
          try {
            fLabel.setText( get() );
          } catch ( InterruptedException e ) {
            e.printStackTrace();
          } catch ( ExecutionException e ) {
            e.printStackTrace();
          }
        }
      }
    }
    

Yes you can do this using SwingWorker thread, do all the pre submitActionPerformed() activities like updating the label, in the execute() method of the currentThread and call doTheTask() as a background job using worker Thread.

I suggest you to go through this documentation for reference about SwingWorker Thread