When should I use javax.swing.SwingUtilities.invokeLater ()?

I have a GUI that uses JProgressBar

. The GUI has JBUTTONs

that call the following code:

public void updateProgressBar(int x) {
    System.out.println(javax.swing.SwingUtilities.isEventDispatchThread());
    healthBar.setValue(x);
}

      

but I also made a loop that calls the same method regularly.

public class Loop implements Runnable {
    public void run() {
        while (true) { Thread.sleep(2000); updateProgressBar(0); }
    }
}

      

Now that I understand everything that changes my GUI needs to be done from EDT. JProgressBar.setValue(x)

changes my GUI and when called from the Loop class the validation isEventDispatchThread

fails, which is nice and straightforward. However, I cannot figure out what this also means what I should be using SwingUtilities.invokeLater()

on setValue()

. It worries me since I don't know how it works setValue()

, what I use invokeLater()

unnecessarily or even break something in using it.

I don't know how to ask my question better: if I know the method that changes my GUI is not called from the EDT, then I also know what I need to use invokeLater()

?

+3


source to share


1 answer


One possible solution is to create a method that checks if the stream is an EDT and if that is so easy to update the panel, otherwise the queue on the EDT:

public void updateProgressBar(int value) {
   progressBar.setValue(value);
}

public void safeUpdateProgressBar(final int value) {
   if (SwingUtilities.isEventDispatchThread()) {
      updateProgressBar(value);
   } else {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            updateProgressBar(value);
         }
      });
   }
}

      



But there are many ways to trick this cat. For example,

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;

public class ProgExample extends JPanel {
   private JProgressBar progressBar = new JProgressBar(0, 100);

   public ProgExample() {
      progressBar.setBorderPainted(true);
      progressBar.setStringPainted(true);
      add(progressBar);
      add(new JButton(new ProgressAction1("Action 1", KeyEvent.VK_1, this)));
      add(new JButton(new ProgressAction2("Action 2", KeyEvent.VK_2, this)));
      add(new JButton(new ProgressAction3("Action 3", KeyEvent.VK_3, this)));
   }

   public void updateProgressBar(int value) {
      progressBar.setValue(value);
   }

   public void safeUpdateProgressBar(final int value) {
      if (SwingUtilities.isEventDispatchThread()) {
         updateProgressBar(value);
      } else {
         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
               updateProgressBar(value);
            }
         });
      }
   }

   private static void createAndShowGui() {
      ProgExample mainPanel = new ProgExample();

      JFrame frame = new JFrame("ProgExample");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class ProgressAction1 extends AbstractAction {
   private static final int MAX_VALUE = 100;
   protected static final long SLEEP_TIME = 100;
   protected static final int STEP = 2;
   private ProgExample gui;

   public ProgressAction1(String name, int mnemonic, ProgExample gui) {
      super(name);
      putValue(MNEMONIC_KEY, mnemonic);
      this.gui = gui;
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      new Thread(new Runnable() {
         private int value = 0;
         @Override
         public void run() {
            while (value <= MAX_VALUE) {
               gui.safeUpdateProgressBar(value);
               value += STEP;
               try {
                  Thread.sleep(SLEEP_TIME);
               } catch (InterruptedException e) {}
            }
            gui.safeUpdateProgressBar(MAX_VALUE);
         }
      }).start();
   }
}

class ProgressAction2 extends AbstractAction {
   private static final int MAX_VALUE = 100;
   protected static final long SLEEP_TIME = 100;
   protected static final int STEP = 2;
   private ProgExample gui;

   public ProgressAction2(String name, int mnemonic, ProgExample gui) {
      super(name);
      putValue(MNEMONIC_KEY, mnemonic);
      this.gui = gui;
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
         private int value = 0;

         @Override
         protected Void doInBackground() throws Exception {
            while (value <= MAX_VALUE) {
               setProgress(value);
               value += STEP;
               try {
                  Thread.sleep(SLEEP_TIME);
               } catch (InterruptedException e) {}
            }
            setProgress(MAX_VALUE);
            return null;
         }
      };
      worker.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent pcEvt) {
            if ("progress".equals(pcEvt.getPropertyName())) {
               gui.updateProgressBar(worker.getProgress());
            }
         }
      });
      worker.execute();
   }
}

class ProgressAction3 extends AbstractAction {
   private static final int MAX_VALUE = 100;
   protected static final int SLEEP_TIME = 100;
   protected static final int STEP = 2;
   private ProgExample gui;

   public ProgressAction3(String name, int mnemonic, ProgExample gui) {
      super(name);
      putValue(MNEMONIC_KEY, mnemonic);
      this.gui = gui;
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      new Timer(SLEEP_TIME, new ActionListener() {
         int value = 0;

         @Override
         public void actionPerformed(ActionEvent e) {
            if (value <= MAX_VALUE) {
               gui.updateProgressBar(value);
               value += STEP;
            } else {
               gui.updateProgressBar(MAX_VALUE);
               ((Timer) e.getSource()).stop();
            }

         }
      }).start();
   }
}

      

+5


source







All Articles