title: Creating delay between GUI updates
body: <p>I am attempting to create a sorting visualizer in Java using Swing. So far, my program asks the user for the sorting algorithm of their choice (I have excluded the code for selection menu here) and then visually sorts an unsorted array. The only sorting algorithm that I have implemented so far for GUI testing purposes is insertion sort.</p>
  
  <p>Below is the insertion sort algorithm: </p>
  
  <pre><code>public class InsertionSort extends Sorter { // Sorter is an abstract class
      @Override
      public void sort(ArrayVisualization array) { // ArrayVisualization object to change array values
          for (int i = 0; i &lt; array.getArraySize(); i++) {
              int j = i - 1;
              int key = array.getArrayValue(i);
              while (j &gt;= 0 &amp;&amp; array.getArrayValue(j) &gt; key) {
                  array.delayedSwap(j, j+1); // calls delayedSwap method continually-PROBLEM
                  --j;
              }
          }
      }
  
      @Override
      public String toString() {
          return "Insertion Sort";
      }
  }
  </code></pre>
  
  <p>I am unable to correctly visualize the swaps between the various indices. At first, I attempted using <code>Thread.sleep()</code> to briefly put the thread to sleep when swapping values. This inevitably ended up freezing the EDT. After searching through Stack Overflow, I came across Swing Timer which is recommended when making GUI modifications. </p>
  
  <p>When I used Swing Timer for <strong>shuffling</strong> the array in <code>shuffleArray()</code>, it worked perfectly fine and I could see each value being swapped with a delay (currently, the portion in <code>shuffleArray()</code> that used Swing Timer is commented because I decided later to not to show the shuffling part with delays). When I implemented the <code>delayedSwap()</code> method in a similar fashion with Swing Timer, the array slightly sorted itself but then suddenly stopped. The array remains unsorted as a whole. </p>
  
  <p><code>delayedSwap()</code> is called appropriate number of times and the insertion sort algorithm works perfectly fine as well when tested without Swing Timer.</p>
  
  <p>Can someone please tell me why am I having this issue with Swing Timer in <code>delayedSwap()</code>?  I have tried using <code>SwingWorker</code> and creating a new thread in <code>delayedSwap()</code> and then putting that to sleep. I kind of think it has something to do with me calling <code>delayedSwap()</code> repeatedly in a loop from another class but I do not understand how else to implement <code>delayedSwap()</code> as that is used in all sorting algorithms (roughly). If this is not fixable, is there any other alternative?</p>
  
  <p>Below is the code for the <code>ArrayVisualizer</code> which contains <code>delayedSwap()</code>.</p>
  
  <pre><code>import javax.swing.*;
  import java.awt.*;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.util.Random;
  
  public class ArrayVisualization extends JPanel {
      private int[] array;
      private static final int BAR_WIDTH = 5;
      private final static int WIN_WIDTH = 1280;
      private final static int WIN_HEIGHT = 720;
      private static final int NUM_BARS = WIN_WIDTH / BAR_WIDTH;
      //private static final int SWAP_DELAY = 1;
  
  
      public void arrayScreen() {
          JFrame frame = new JFrame("Sorting Visualizer");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
          frame.setLayout(new BorderLayout());
  
          ArrayVisualization panel = new ArrayVisualization();
          frame.add(panel);
  
          frame.setSize(WIN_WIDTH, WIN_HEIGHT);
          frame.setVisible(true);
          frame.setResizable(false);
          frame.setLocationRelativeTo(null);
      }
  
      public int getArraySize() {
          return this.array.length;
      }
  
      public int getArrayValue(int x) {
          return this.array[x];
      }
  
      public ArrayVisualization() { 
          array = new int[NUM_BARS];
          for (int i = 0; i &lt; NUM_BARS; i++) { // populate the array
              array[i] = i;
          }
          shuffleArray(); // shuffle
          InsertionSort sort = new InsertionSort();
          sort.sort(this); // sort
      }
  
      public void shuffleArray() {
          Random rand = new Random();
  
          for (int i = 0; i &lt; NUM_BARS; i++) {
              int randIdx = rand.nextInt(NUM_BARS - 1); // create random indices to swap with
              int temp = array[randIdx];
              array[randIdx] = array[i];
              array[i] = temp;
          }
          repaint(); 
  
   /*       Timer timer = new Timer(1, new ActionListener() {
              private int counter;
  
              @Override
              public void actionPerformed(ActionEvent e) {
                  int randomNumber = rand.nextInt(NUM_BARS - 1);
  
                  int temp = array[counter];
                  array[counter] = array[randomNumber];
                  array[randomNumber] = temp;
                  repaint();
                  if (counter == NUM_BARS - 1) {
                      ((Timer)e.getSource()).stop();
                  }
                  counter++;
              }
          });
          timer.start();*/
      }
  
  /* MAIN PROBLEM */
      public void delayedSwap(int idx1, int idx2) {
          Timer timer = new Timer(1000, new ActionListener() {
              @Override
              public void actionPerformed(ActionEvent e) {
  
                  int temp = array[idx1];
                  array[idx1] = array[idx2];
                  array[idx2] = temp;
                  repaint();
                  ((Timer) e.getSource()).stop(); // so that timer terminates after 1 swap
              }
          });
          timer.start();
      }
  
  
      @Override
      public void paintComponent(Graphics g) {
          Graphics2D graphics = (Graphics2D) g;
          super.paintComponent(graphics);
  
  
          graphics.setColor(Color.BLACK);
          for (int i = 0; i &lt; NUM_BARS; i++) {
              int height = array[i] * 2;
              int xBegin = i + (BAR_WIDTH - 1) * i;
              int yBegin = WIN_HEIGHT - height;
  
              graphics.fillRect(xBegin, yBegin, BAR_WIDTH, height);
          }
      }
  }
  </code></pre>
  
  <p>Thank you!</p>