http://www.youtube.com/watch?v=M0cNsmjK33E
我想使用 Java Swing 开发类似于上面链接的东西。我有排序方法,并且在重新绘制时执行了操作,但是当我触发排序时,它没有显示条形图缓慢地自行排序,而是卡住,然后在数组完全排序后解冻。
我该如何解决这个问题? 编辑:抱歉忘记了代码。它是一个非常简单的图形用户界面。另一个用于排序的类对整个数组进行排序
public class SortGUI {
JFrame frame;
int frameWidth = 1000, frameHeight = 1000;
int panelWidth, panelHeight;
DrawPanel panel;
JPanel panel2;
JScrollPane scroll;
JViewport view;
static int[] S = new int[50000];
public static void main(String[] args) throws InterruptedException {
SortGUI app = new SortGUI();
initializeArray();
app.go();
}
public static void initializeArray()
{
for (int i = 0; i < S.length; i++) {
S[i] = (int) (Math.random() * 16581375);
}
}
public void go() throws InterruptedException {
//Frame
frame = new JFrame();
frame.setSize(frameWidth, frameHeight);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//panel
panel = new DrawPanel();
scroll = new JScrollPane(panel,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
//Layout
frame.add(scroll);
frame.addKeyListener(new keyListener());
while(true)
{
panel.repaint();
}
}
public class DrawPanel extends JPanel
{
public DrawPanel()
{
this.setPreferredSize(new Dimension(50000,930));
}
public void paintComponent(Graphics g)
{
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
for(int i = 0; i < S.length; i++)
{
int red = S[i] / 65025;
int green = (S[i] > 65025)? S[i] % 65025 : 0;
int blue = green;
blue %= 255;
green /= 255;
g.setColor(new Color(red,green,blue));
g.fillRect(i, 900 - (S[i] / 18500), 1, S[i] / 18500);
}
}
}
public class keyListener implements KeyListener{
public void keyTyped(KeyEvent ke) {
}
public void keyPressed(KeyEvent ke) {
if(ke.getKeyChar() == '1')
{
sorter.bubbleSort(S);
}
}
public void keyReleased(KeyEvent ke) {
}
}
}
最佳答案
注意:我在问题被删除之前开始写这个
很可能您使用某种循环机制并祈祷每次迭代,用户界面都会更新。这是一个错误的假设。在循环完成之前,UI不会更新。您所做的就是我们所说的阻塞事件调度线程(EDT)
参见How to use a Swing Timer 。在 ActionListener 回调中进行“迭代”更新。例如,如果您想要为排序算法设置动画,则需要确定计时器回调的每个“迭代”需要更新的内容。然后每次迭代都会重新绘制 ui。
所以你的计时器可能看起来像这样
Timer timer = new Timer(40, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
if (sortingIsDone()) {
((Timer)e.getSource()).stop();
} else {
sortOnlyOneItem();
}
repaint();
}
});
您的 sortOnlyOneItem
方法应该只对一项进行排序。并有某种标志来检查排序是否完成,然后停止计时器。
其他说明:
- 如果您不打算自己绘制背景,则应该在
paintComponent
方法中调用super.paintComponent
。一般来说我总是这样做。
这是一个完整的示例。我很高兴你自己想出了办法。在我看到你明白之前我正在研究这个例子。
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collections;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class SelectionSortAnimate extends JPanel {
private static final int NUM_OF_ITEMS = 20;
private static final int DIM_W = 400;
private static final int DIM_H = 400;
private static final int HORIZON = 350;
private static final int VERT_INC = 15;
private static final int HOR_INC = DIM_W / NUM_OF_ITEMS;
private JButton startButton;
private Timer timer = null;
private JButton resetButton;
Integer[] list;
int currentIndex = NUM_OF_ITEMS - 1;
public SelectionSortAnimate() {
list = initList();
timer = new Timer(200, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (isSortingDone()) {
((Timer) e.getSource()).stop();
startButton.setEnabled(false);
} else {
sortOnlyOneItem();
}
repaint();
}
});
startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
resetButton = new JButton("Reset");
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
list = initList();
currentIndex = NUM_OF_ITEMS - 1;
repaint();
startButton.setEnabled(true);
}
});
add(startButton);
add(resetButton);
}
public boolean isSortingDone() {
return currentIndex == 0;
}
public Integer[] initList() {
Integer[] nums = new Integer[NUM_OF_ITEMS];
for (int i = 1; i <= nums.length; i++) {
nums[i - 1] = i;
}
Collections.shuffle(Arrays.asList(nums));
return nums;
}
public void drawItem(Graphics g, int item, int index) {
int height = item * VERT_INC;
int y = HORIZON - height;
int x = index * HOR_INC;
g.fillRect(x, y, HOR_INC, height);
}
public void sortOnlyOneItem() {
int currentMax = list[0];
int currentMaxIndex = 0;
for (int j = 1; j <= currentIndex; j++) {
if (currentMax < list[j]) {
currentMax = list[j];
currentMaxIndex = j;
}
}
if (currentMaxIndex != currentIndex) {
list[currentMaxIndex] = list[currentIndex];
list[currentIndex] = currentMax;
}
currentIndex--;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < list.length; i++) {
drawItem(g, list[i], i);
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(DIM_W, DIM_H);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Sort");
frame.add(new SelectionSortAnimate());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
关于Java swing在计算时重新绘制: animating sorting algorithm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24585911/