如何在算法结束之前重新绘制排序算法的每次迭代?

How do I repaint each iteration of a sorting algorithm before the algorithm ends?

我不熟悉使用 Java Swing 和排序算法可视化工具。我已经列出了矩形并给出了仅用于测试的基础知识,但我 运行 遇到了一些困难。我想在一次排序迭代后每次更改它时使用 repaint() 函数重新绘制矩形,但程序似乎并没有一步一步地进行,而是跳到完全排序的数组。我尝试添加延迟,但这使程序根本无法运行。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@SuppressWarnings("serial")
class Panel extends JPanel implements ActionListener, KeyListener {
    // All Global varaibles
    private Timer myTimer= new Timer( 30, this );
    int width = 100;
    int height_bounds = 400;
    Random rand = new Random();
    int[] height = new int[width];

    public Panel(){
        for (int i = 0; i < width; i++) {
            height[i] = rand.nextInt(height_bounds)+50;
        }
        myTimer.start();
    }

    public void paintComponent(Graphics gr){
            super.paintComponent(gr);
            //setBackground(new Color(0,0,0));
            for (int i=0; i<width; i++) {
                gr.drawRect(i*10+81, 740-height[i], 4, height[i]);
            }
    }

    @Override
    public void keyPressed(KeyEvent ev) {}
    @Override
    public void keyReleased(KeyEvent arg0) {}
    @Override
    public void keyTyped(KeyEvent arg0) {}
    @Override
    public void actionPerformed(ActionEvent e) {
            
        for (int i = 0; i < width; i++){
            for (int j = 0; j < width-1; j++){
                if (height[j] > height[j+1]) 
                { 
                    // swap arr[j+1] and arr[i] 
                    int temp = height[j]; 
                    height[j] = height[j+1]; 
                    height[j+1] = temp;
                } 
            }
          repaint();
        }
        
    }
}

如果您要在 actionPerformed 中进行排序,那么您将阻止 UI 重新绘制,因为它是由为您修复 UI 的完全相同的线程执行的。将处理移动到单独的线程并从那里安排重绘,例如

public void actionPerformed(ActionEvent e) {
    new Thread(()=>{    
    for (int i = 0; i < width; i++){
        for (int j = 0; j < width-1; j++){
            if (height[j] > height[j+1]) 
            { 
                // swap arr[j+1] and arr[i] 
                int temp = height[j]; 
                height[j] = height[j+1]; 
                height[j+1] = temp;
            } 
        }
      SwingUtils.invokeLater(()=>repain());
      Thread.sleep(500); // add some meaningfull value
    }
    }).start();
}

显然你应该使用线程池而不是创建新线程,在每次点击后阻止多个线程同时启动并且可能为此使用 SwingWorker,但它应该让你了解流程。