title: Disable JButton, while background job, to avoid multiple clicks
body: <p>I need to stop user making multiple clicks on a JButton while the first click still execute.</p>
  
  <p>I was able to came with a solution for this issue but I do not completelly understand why it's working. </p>
  
  <p>Bellow I posted the code (trimmed to a minimum) that works and the one that does not work.</p>
  
  <p>In first example (good) if you run it and click the button multiple times only one action is considered as for the second example (bad) if you click the mouse multiple times you get action executed at least twice.</p>
  
  <p>The second (bad) example simply does not use invokeLater() method.</p>
  
  <p>Where the difference in behaviour cames from? </p>
  
  <pre class="lang-java prettyprint-override"><code>import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import javax.swing.*;
  
  public class TestButtonTask {
  
      public static void main(String[] args) {
  
          final JFrame frame = new JFrame("Test");
          frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
  
          final JButton task = new JButton("Test");
  
          task.addActionListener(new ActionListener() {
  
              @Override
              public void actionPerformed(ActionEvent e) {
                  long t = System.currentTimeMillis();
                  System.out.println("Action received");
  
                  task.setText("Working...");
                  task.setEnabled(false);
  
                  SwingUtilities.invokeLater(new Thread() {
  
                      @Override
                      public void run() {
                          try {
                              sleep(2 * 1000);
                          } catch (InterruptedException ex) {
                              Logger.getLogger(TestButtonTask.class.getName()).log(Level.SEVERE, null, ex);
                          }
  
                          SwingUtilities.invokeLater(new Runnable() {
  
                              public void run() {
                                  task.setEnabled(true);
                                  task.setText("Test");
                              }
                          });
  
                      }
                  });
              }
          });
  
          frame.add(task);
          frame.pack();
          frame.setVisible(true);
      } //end main
  } //end class
  </code></pre>
  
  <p>And now the "wrong" code</p>
  
  <pre class="lang-java prettyprint-override"><code>import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import javax.swing.*;
  
  public class TestButtonTask {
  
      public static void main(String[] args) {
  
          final JFrame frame = new JFrame("Test");
          frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
  
          final JButton task = new JButton("Test");
  
          task.addActionListener(new ActionListener() {
  
              @Override
              public void actionPerformed(ActionEvent e) {
                  long t = System.currentTimeMillis();
                  System.out.println("Action received");
  
                  task.setText("Working...");
                  task.setEnabled(false);
  
                  SwingUtilities.invokeLater(new Thread() {
  
                      @Override
                      public void run() {
                          try {
                              sleep(2 * 1000);
                          } catch (InterruptedException ex) {
                              Logger.getLogger(TestButtonTask.class.getName()).log(Level.SEVERE, null, ex);
                          }
  
                          //SwingUtilities.invokeLater(new Runnable() {
  
                              //public void run() {
                                  task.setEnabled(true);
                                  task.setText("Test");
                              //}
                          //});
  
                      }
                  });
              }
          });
  
          frame.add(task);
          frame.pack();
          frame.setVisible(true);
      } //end main
  } //end class
  </code></pre>
  
  <p>After info provided by @kleopatra and @Boris Pavlović here is the code I created that seems to work pretty decent.</p>
  
  <pre class="lang-java prettyprint-override"><code>import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.beans.PropertyChangeEvent;
  import java.beans.PropertyChangeListener;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import javax.swing.*;
  
  public class TestButtonTask {
  
      public static void main(String[] args) {
  
          final JFrame frame = new JFrame("Test");
          frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
  
          final JButton task = new JButton("Test");
  
          task.addActionListener(new ActionListener() {
  
              @Override
              public void actionPerformed(ActionEvent e) {
                  task.setText("Working...");
                  task.setEnabled(false);
  
                  SwingWorker worker = new SwingWorker&lt;Void, Void&gt;() {
  
                      @Override
                      protected Void doInBackground() throws Exception {
                          try {
                              Thread.sleep(3 * 1000);
                          } catch (InterruptedException ex) {
                              Logger.getLogger(TestButtonTask.class.getName()).log(Level.SEVERE, null, ex);
                          }
  
                          return null;
                      }                    
                  };
  
                  worker.addPropertyChangeListener(new PropertyChangeListener() {
                      @Override
                      public void propertyChange(PropertyChangeEvent evt) {
                          System.out.println("Event " + evt + " name" + evt.getPropertyName() + " value " + evt.getNewValue());
                          if ("DONE".equals(evt.getNewValue().toString())) {
                              task.setEnabled(true);
                              task.setText("Test");
                          }
                      }
                  });
  
                  worker.execute();
              }
          });
  
          frame.add(task);
          frame.pack();
          frame.setVisible(true);
      } //end main
  } //end class
  </code></pre>