当前位置: 代码迷 >> java >> 使用Thread.sleep时如何更新UI
  详细解决方案

使用Thread.sleep时如何更新UI

热度:38   发布时间:2023-07-31 13:40:28.0

当运行我的BubbleSort方法时,我希望面板进行更新以显示正在发生的事情,但是使用Thread.sleep时面板会冻结直到该方法结束为止。

我听说过使用Swing计时器,我知道如何使用它们,但不知道如何才能在中间方法中实现它们以暂停和继续。

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);
    }
}  

我希望面板在方法运行时进行更新,但是在方法完成之前使用的面板保持空白。

您正在放置Thread.sleep(500); 直接在UI线程上。 而是为气泡排序创建新线程。 因此,如果您将睡眠置于UI线程以外的线程上,则不会冻结UI。

更改ActionListner以便在单独的线程中完成排序:

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

要使用Swing线程更新UI,请使用: SwingUtilities.invokeLater(()->repaint()); 而不是this.repaint();

您正在进行分类并在EDT中入睡

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

这就是所谓的“ GUI”线程, actionPerformed由它完成。 EDT负责UI的绘制和响应。 您正在窒息,因此冻结。 使用SwingWorker进行计算(和休眠)并publish中间结果,以便GUI可以反映所做的更改。

  相关解决方案