计算时的Java swing重绘:动画排序算法

http://www.youtube.com/watch?v=M0cNsmjK33E

我想使用Java Swing开发类似于上面链接的东西。 我有排序方法,并在重绘时完成,但是当我触发排序时,它不是显示条慢慢排序本身,而是在数组完全排序时冻结然后解冻。

我该如何解决? 编辑:抱歉忘了密码。 它是一个非常简单的gui。 另一个用于排序的类对整个数组进行排序

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  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都要更新。 这是一个错误的假设。 在循环结束之前,UI 不会更新。 你在做什么是我们所说的阻止事件调度线程(EDT)

请参见如何使用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); } }); } }