在for循环中重新绘制

3

可能重复:
如何使用Swing制作动画?

在Swing中,我对数组进行排序并希望对其进行动画处理。每次在循环中更新数组时,我都有另一个while循环来产生暂停效果,并且当我调用repaint()时实际上并没有被调用。为什么它不起作用? Thread.sleep(1000); 会冻结应用程序并且不会恢复。

    public class Shape extends JPanel  {

    private static final long serialVersionUID = 1L;
    public int col;
    public JButton b2 = new JButton("Sort");
    public Rectangle2D.Double table = null;
    public ArrayList<Integer> arr = null;

    public Shape(){

        initArray(); // initialize array with random number of random numbers
        table = new Rectangle2D.Double(10,10,400,400);
        add(b2); // button sort

        b2.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                            System.out.println("sort it!");
                            Sort(arr);
                            display(arr);
                    }
         });
    }

    public void initArray() {
        col = generateRandom(10,20);            // generate a random number of bars 10 - 20
        arr = new ArrayList<Integer>(col);

        for(int i = 0; i < col; i++){
                // for each bar generate a random height 10 - 300
                int h = generateRandom(10, 390);
                arr.add(h);
        }
    }


    public void paintComponent(Graphics g){
        System.out.println("check");
        clear(g);
        Graphics2D g2d = (Graphics2D)g;
        System.out.println(arr.size());
        for(int j = 0; j < arr.size(); j++) {
                g2d.drawRect(j*20+20,410-arr.get(j),20,arr.get(j));
        }
    }

    protected void clear(Graphics g){
        super.paintComponent(g);
    }

    /*
     * generate random number in the range from 1 to 400
     */
    private int generateRandom(int start, int end){
        return new Random().nextInt(end)+start;
    }

    public void Sort(ArrayList<Integer> arr) {
        int t = 0;

        boolean swap = true;
        do {
                swap = false;
                for(int i = 0; i < arr.size() - 1; i++) {
                        if(arr.get(i).compareTo(arr.get(i+1)) > 0) {
                                int temp = arr.get(i);
                                arr.set(i, arr.get(i+1));
                                arr.set(i+1, temp);
                                swap = true;
                                // iterate to make effect of pausing
                                while(t < 100) {display(arr);t++;}
                                t = 0;
                                // repaint array
                                repaint();
                        }
                }
        } while(swap);
    }

    static void display(ArrayList<Integer> arr) {
        for(int i = 0; i < arr.size()-1; i++)
                System.out.print(arr.get(i) + ", ");
        System.out.println(arr.get(arr.size()-1));
    }

    public static void main(String[] arg){
        WindowUtilities.openInJFrame(new Shape(), 500,500);  
    }
}

请查看我在stackoverflow上的这个答案。该答案的开头可以让您对为什么您的repaint没有被调用(尽管只有队列中的第一个repaint()被调用,其余的都被丢弃)做出公正的判断。此答案还阐述了如何在循环内重绘,尽管由于某些限制条件,这种方法并不经常使用。 - nIcE cOw
1个回答

7
不要在Swing中使用Thread.sleep,因为它会阻止UI。相反,要使用javax.swing.Timer:每次计时器触发操作监听器时,您都可以更新数组并安排重新绘制。这将提供您所需的动画效果。
另请参见:

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接