我想创建一个Java应用程序,使用swing组件可视化合并排序。到目前为止,我已经写了这个:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class MergeSort extends JFrame {
private int[] helper;
private int[] heights;
private JPanel mainPanel;
private JTextArea[] areas;
private JTextArea txtSpeed;
private JLabel lblSpeed;
private JButton btnStart;
private Random rnd;
private final int FRAME_HEIGHT = 550;
private final int FRAME_WIDTH = 1100;
private final int ELEMENTS_TO_SORT = 100;
private final int BAR_WIDTH = 7;
private final int SPACING = 10;
private int SLEEP_TIME = 50;
public MergeSort() {
super("Merge Sort Visualisation");
helper = new int[ELEMENTS_TO_SORT];
mainPanel = new JPanel();
mainPanel.setLayout(null);
rnd = new Random();
areas = new JTextArea[ELEMENTS_TO_SORT];
heights = new int[areas.length];
for (int i = 0; i < areas.length; i++) {
areas[i] = new JTextArea();
heights[i] = rnd.nextInt(FRAME_HEIGHT - 100);
mainPanel.add(areas[i]);
areas[i].setSize(BAR_WIDTH, heights[i]);
areas[i].setLocation((i + 1) * SPACING,
FRAME_HEIGHT - areas[i].getHeight());
areas[i].setText(toDigits(heights[i]));
}
btnStart = new JButton("Start");
btnStart.addActionListener(
new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
setSleepTime(Integer.parseInt(txtSpeed.getText()));
sort();
} catch (NumberFormatException ex) {
//s
} catch (InterruptedException ex) {
//i
}
}
}
);
mainPanel.add(btnStart);
btnStart.setSize(100, 25);
btnStart.setLocation(0, 25);
txtSpeed = new JTextArea("50");
mainPanel.add(txtSpeed);
txtSpeed.setSize(100, 25);
txtSpeed.setLocation(0, 0);
lblSpeed = new JLabel("Sleep Time");
mainPanel.add(lblSpeed);
lblSpeed.setSize(100, 25);
lblSpeed.setLocation(110, 0);
this.add(mainPanel);
this.setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
private void setSleepTime(int x) {
if (x >= 0) {
SLEEP_TIME = x;
} else {
SLEEP_TIME = 0;
}
}
public void sort() throws InterruptedException {
mergesort(0, heights.length - 1);
}
private void mergesort(int low, int high) throws InterruptedException {
if (low < high) {
int middle = low + (high - low) / 2;
mergesort(low, middle);
mergesort(middle + 1, high);
merge(low, middle, high);
}
}
private void merge(int low, int middle, int high) throws InterruptedException {
for (int i = low; i <= high; i++) {
helper[i] = heights[i];
}
int i = low;
int j = middle + 1;
int k = low;
while (i <= middle && j <= high) {
if (helper[i] <= helper[j]) {
heights[k] = helper[i];
updateAreaX(k);
Thread.currentThread().sleep(SLEEP_TIME);
i++;
} else {
heights[k] = helper[j];
updateAreaX(k);
Thread.currentThread().sleep(SLEEP_TIME);
j++;
}
k++;
}
// Copy the rest of the left side of the array into the target array
while (i <= middle) {
heights[k] = helper[i];
updateAreaX(k);
Thread.currentThread().sleep(SLEEP_TIME);
k++;
i++;
}
}
private String toDigits(int a) {
StringBuilder bdr = new StringBuilder();
while (a > 0) {
bdr.insert(0, Integer.toString(a % 10) + String.format("%n"));
a /= 10;
}
if (bdr.length() > 0) {
bdr.setLength(bdr.length() - 1);
}
return bdr.toString();
}
private void updateAreaX(int x) {
areas[x].setSize(BAR_WIDTH, heights[x]);
areas[x].setLocation(areas[x].getLocation().x,
FRAME_HEIGHT - areas[x].getHeight() - 40);
areas[x].setText(toDigits(heights[x]));
}
public static void main(String[] args) throws InterruptedException {
MergeSort sorter = new MergeSort();
sorter.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
sorter.setVisible(true);
}
}
问题是当我点击开始按钮时,整个JFrame会冻结,直到所有内容都被排序,然后显示结果。如果我没有通过按钮启动sort()
方法,而是在public static void main()中编写sorter.sort()
它可以工作。我该如何解决?我想我需要将排序放在另一个线程或其他东西上,但我不知道如何。
答案 0 :(得分:3)
您的下一个问题:您在EDT
中屏蔽了ActionListener
,因为您的框架会冻结,直到actionPerformed()
方法退出。当您使用Thread.sleep(...)
时,它无法帮助Swing
重绘您的画面。
似乎您需要使用Swing Timer
进行更新。此外,您可以使用SwingWorker
进行长时间的后台处理。