如何在算法结束之前重新绘制排序算法的每次迭代?
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,但它应该让你了解流程。
我不熟悉使用 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,但它应该让你了解流程。