将repaint()与Thread.Sleep()结合使用

时间:2012-01-09 16:47:04

标签: java swing repaint thread-sleep

我试图做的很简单,我想在屏幕上显示算法的步骤,因此我试图将repaint()与sleep()结合起来,但我做错了,我喜欢它,如果有人知道这个问题,首先要解释这个代码的错误,其次,我该怎么做才能使它工作......

谢谢!

总之,这段代码的意思是绘制10个红色顶点,然后以200毫秒的间隔逐个进行balcken。

这是代码:

public class Tester {

       public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    ShowGUIGraph();
                }
            });
        }

        private static void ShowGUIGraph() {
            JFrame f = new JFrame("something");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JPanel p=new JPanel();
            p.setLayout(new BorderLayout());
            p.add(BorderLayout.CENTER,new SomePanel());
            f.add(p);
            f.setPreferredSize(new Dimension(800,600));
            f.pack();
            f.setVisible(true);
        }
}

public class SomePanel extends JPanel {
    private static final long serialVersionUID = 1L;
    LinkedList<Vertex> vertices=new LinkedList<Vertex>();
    public SomePanel () {
        for (int i=0;i<10;i++) {
            Vertex v=new Vertex(i);
            v.setLocation(20+30*i, 20+30*i);
            vertices.add(v);
        }
        traverseVerticesRecoursive(0);
        traverseVerticesNonRecoursive();
    }
    public void traverseVerticesRecoursive(int i) {
        if (i>=vertices.size()) return;
        vertices.get(i).setColor(Color.black);

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        repaint();
        traverseVerticesRecoursive(i+1);
    }
    public void traverseVerticesNonRecoursive() {
        for (int i=0;i<10;i++) {
            vertices.get(i).setColor(Color.red);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            repaint();
        }
    }
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int i=0;i<vertices.size();i++) {
            vertices.get(i).paintVertex(g);
        }

    }
}
   public class Vertex {
        private int x,y,tag,r=20;
        private Color color=Color.red;
        Vertex (int i) {
            tag=i;
        }
        public void setLocation(int x0,int y0) {
            x=x0;
            y=y0;
        }
        public int getX() {
            return x;
        }
        public int getY() {
            return y;
        }

        public void setColor(Color c) {
            color=c;
        }
        public boolean colorIs(Color c) {
            return (color.equals(c));
        }

        public void paintVertex(Graphics g) {
            g.setColor(color);
            g.fillOval(x,y,r,r);
            g.setColor(Color.BLACK);
            g.drawOval(x,y,r,r);
            g.drawString(""+tag, x+r/2, y+r/2+4);
        }
        public int getR() {
            return r;
        }
    }

4 个答案:

答案 0 :(得分:4)

不要在Event Dispatch Thread中睡觉;这将导致GUI冻结。对于动画,请使用EDT友好的实用程序类,例如javax.swing.Timer

答案 1 :(得分:1)

可能会使您的代码更清晰的一些想法:

  1. SomePanel类中,将遍历代码放在构造函数之外的方法中。构造函数用于初始化字段。
  2. 首先启动静态GUI,然后生成一个工作线程,通过前面的方法进行更新(这将是你的小“引擎”)。在这个帖子中你可以打电话给sleep
  3. traverseVerticesRecoursive方法中,只对UI线程进行重绘,并在工作线程上进行状态更新。
  4. 你应该做的主要修改是不要阻止带有睡眠呼叫的GUI线程,正如他们在第一个答案中告诉你的那样。

答案 2 :(得分:0)

Thread.sleep是一项长期任务。当您在EDT中运行此类任务时,它会阻止执行所有重新绘制请求。所有待处理的重绘请求和在睡眠阶段发送的重新排序请求都会排队等待以后处理。

结果,当EDT退出sleep阶段时,它将所有这样的重绘请求(如果启用了合并,这是默认属性)合并为一个重新执行的执行。如果未启用合并,则所有排队的请求将按顺序执行,两者之间没有任何时间间隔。结果似乎UI没有更新。

要纠正这种情况,请使用timer,它会在特定的时间间隔后定期触发。

答案 3 :(得分:0)

盖伊,你可以使用新的线程与EDT线程不同来制作动画。例如,

 void play() {
    Thread thread = new Thread() {
        @Override
        public void run() {
            game();
        }
    };
    thread.start();
}

void game() {
    for (; ; ) {
        switch (state) {
            case GameData.ANIMATING:
                // call some function as repaint() to update GUI
                break;
            case GameData.GAME_ENDED:
                return;
            default:
                break;
        }

        diffTime = System.currentTimeMillis() - beforeTime;
        sleepTime = delay - diffTime;
        sleepTime = (sleepTime < 0) ? 0 : sleepTime;
        Thread.sleep(sleepTime);
    }
}