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

huangapple go评论65阅读模式
英文:

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

问题

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 variables
	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();
		}
		
	}
}
英文:

I am new to using Java Swing and working on a sorting algorithm visualizer. I have set out the rectangles and gave the basics done just for testing, but I ran into some difficulties. I wanted to use the repaint() function to repaint the rectangles every time I changed it after one iteration of sort, but the program does not seem to be doing it step by step, rather it skips to the array fully sorted. I tried adding a delay but that makes the program not work at all.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@SuppressWarnings(&quot;serial&quot;)
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 &lt; 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&lt;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 &lt; width; i++){
for (int j = 0; j &lt; width-1; j++){
if (height[j] &gt; height[j+1]) 
{ 
// swap arr[j+1] and arr[i] 
int temp = height[j]; 
height[j] = height[j+1]; 
height[j+1] = temp;
} 
}
repaint();
}
}
}

答案1

得分: 1

如果您在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]) 
                { 
                    // 交换 arr[j+1] 和 arr[i] 
                    int temp = height[j]; 
                    height[j] = height[j+1]; 
                    height[j+1] = temp;
                } 
            }
            SwingUtils.invokeLater(() -> repain());
            Thread.sleep(500); // 添加一些有意义的值
        }
    }).start();
}

显然,您应该使用线程池而不是创建新线程,阻止在每次点击后同时启动多个线程,并且可能使用SwingWorker来实现,但这应该给您一个流程的想法。

英文:

If you are going doing your sorting in actionPerformed then you are blocking UI from beeing redrawn since it is executed by the exact same thread that would repaing UI for you. Move processing to separate thread and schedule repaint from therem eg

public void actionPerformed(ActionEvent e) {
new Thread(()=&gt;{    
for (int i = 0; i &lt; width; i++){
for (int j = 0; j &lt; width-1; j++){
if (height[j] &gt; 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(()=&gt;repain());
Thread.sleep(500); // add some meaningfull value
}
}).start();
}

Obviously you should use thread pool instead of creating new tread, block multiple thread starting at the same time after every click and probably use SwingWorker for that, but it should give you an idea of the flow.

huangapple
  • 本文由 发表于 2020年7月27日 15:01:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/63110228.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定