Edd
Edd

Reputation: 136

How to update UI when using Thread.sleep

When running my BubbleSort method I want a panel to update showing exactly what is happening, however the panel freezes until the method has fniished when using Thread.sleep.

I've heard about using Swing timers and I know how to use them but do not know how I could implement them 'mid-method' to pause and continue.

import java.awt.Color;
import java.awt.Font;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;

@SuppressWarnings("serial")
public class BubbleSort extends JPanel implements ActionListener
{  
    int swaps;
    int maxswaps;
    int[] array;
    JLabel arrayLabel;
    JLabel tipLabel = new JLabel();;

    private void bubbleSort(int[] array)
    {  
        maxswaps = (int) Math.pow(array.length,2);
        int tempnum = 0;  
        for(int i=0; i < array.length; i++)
        {  
            for(int num=1; num < (array.length-i); num++)
            {  
                if(array[num-1] > array[num])
                {  
                    tempnum = array[num-1];  
                    array[num-1] = array[num];  
                    array[num] = tempnum;  
                    tipLabel.setText("Swapping " + tempnum + " and " + array[num-1]);
                    arrayLabel.setText(Arrays.toString(array));
                    this.repaint();
                    swaps++;
                    try
                    {
                        Thread.sleep(500);
                        // this is where I want it to sleep         
                    }
                    catch (InterruptedException e)
                    {

                    }

                } 
            }  
        }  
    }  



    public static void moveToMiddle(JFrame frame)
    {
        GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
        int screenWidth = gd.getDisplayMode().getWidth();
        int screenHeight = gd.getDisplayMode().getHeight();
        frame.setBounds((screenWidth/2) - (frame.getWidth()/2), (screenHeight/2) - (frame.getHeight()/2), frame.getWidth(), frame.getHeight());
    }

    public static void main(String[] args)
    {  
        JPanel panel = new BubbleSort();
        panel.setLayout(null);
        panel.setBackground(Color.WHITE);
        panel.setFocusable(true);

        JFrame frame = new JFrame("Bubble Sort");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);        
        frame.setSize(800, 500);
        frame.setContentPane(panel);
        frame.setVisible(true);
        moveToMiddle(frame);
    }  

    public BubbleSort()
    {
        int arrayLength = 12;
        int maxNumber = 100;
        int minNumber = 0;

        array = new int[arrayLength]; 
        Random r = new Random();
        for(int i=0; i < array.length; i++)
        {
            int num = r.nextInt(maxNumber) + minNumber;
            array[i] = num;
        }

        arrayLabel = new JLabel(Arrays.toString(array));
        arrayLabel.setFont(new Font("Bahnschrift", Font.PLAIN, 35));
        arrayLabel.setBounds(100, 100, 600, 100);

        tipLabel.setBounds(100 , 250 , 600, 100);
        tipLabel.setFont(new Font("Bahnschrift", Font.PLAIN, 35));

        tipLabel.setVerticalAlignment(SwingConstants.CENTER);
        tipLabel.setHorizontalAlignment(SwingConstants.CENTER);

        arrayLabel.setVerticalAlignment(SwingConstants.CENTER);
        arrayLabel.setHorizontalAlignment(SwingConstants.CENTER);

        JButton startButton = new JButton("Start");
        startButton.addActionListener(this);
        startButton.setBounds(0,0,50,50);

        this.add(arrayLabel);   this.add(tipLabel); this.add(startButton);
    }

    @Override
    public void actionPerformed(ActionEvent arg0)
    {
        bubbleSort(array);
    }
}  

I want the panel to update whilst the method is running but using it remains blank until the method has finished.

Upvotes: 1

Views: 758

Answers (3)

c0der
c0der

Reputation: 18792

Change the ActionListner so the sorting is done on a separate thread:

@Override
public void actionPerformed(ActionEvent arg0)
{
    new Thread(()->bubbleSort(array)).start();
}

To update UI using Swing thread use : SwingUtilities.invokeLater(()->repaint()); instead of this.repaint();

Upvotes: 2

Antoniossss
Antoniossss

Reputation: 32535

You are doing the sorting AND the sleeping in EDT

   @Override
    public void actionPerformed(ActionEvent arg0)
    {
        bubbleSort(array);
    }

This is so called "GUI" thread and actionPerformed is done by it. EDT is responsible for drawing and responsiveness of the UI. You are chocking it, thus freeze. Use SwingWorker to do computation (and sleeping) and publish intermediate results so the GUI may reflect the changes.

Upvotes: 1

Joy
Joy

Reputation: 424

You are placing Thread.sleep(500); directly on UI thread. Instead create new thread for bubble sort. So if you put sleep on thread other than UI thread it will not freeze your UI.

Upvotes: 2

Related Questions