Java 将repaint()与Thread.Sleep()相结合

Java 将repaint()与Thread.Sleep()相结合,java,swing,repaint,thread-sleep,Java,Swing,Repaint,Thread Sleep,我想做的很简单,我想在屏幕上展示一个算法的步骤,因此为什么我要尝试将repaint()与sleep()结合起来,但我做得不对,如果有人对它有足够的了解,首先解释一下这段代码的错在哪里,其次,我该怎么做才能让它工作 谢谢 在Summey中,这段代码要做的是绘制10个红色顶点,然后以200毫秒的间隔逐个消除它们 代码如下: public class Tester { public static void main(String[] args) { SwingU

我想做的很简单,我想在屏幕上展示一个算法的步骤,因此为什么我要尝试将repaint()与sleep()结合起来,但我做得不对,如果有人对它有足够的了解,首先解释一下这段代码的错在哪里,其次,我该怎么做才能让它工作

谢谢

在Summey中,这段代码要做的是绘制10个红色顶点,然后以200毫秒的间隔逐个消除它们

代码如下:

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;
        }
    }
公共类测试器{
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
ShowGUIGraph();
}
});
}
私有静态void ShowGUIGraph(){
JFrame f=新的JFrame(“某物”);
f、 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p=新的JPanel();
p、 setLayout(新的BorderLayout());
p、 添加(BorderLayout.CENTER,newsomepanel());
f、 加(p);
f、 设置首选尺寸(新尺寸(800600));
f、 包装();
f、 setVisible(真);
}
}
公共类SomePanel扩展了JPanel{
私有静态最终长serialVersionUID=1L;
LinkedList顶点=新建LinkedList();
公共事务委员会(){
for(int i=0;i=vertices.size())返回;
顶点.get(i).setColor(Color.black);
试一试{
睡眠(200);
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
重新油漆();
横切反射(i+1);
}
public void TraverseVertices非递归(){

对于(int i=0;i不在事件调度线程中休眠;这将导致GUI冻结。对于动画,请使用EDT友好的实用程序类,例如。

不要在事件调度线程中休眠;这将导致GUI冻结。对于动画,请使用EDT友好的实用程序类,例如。

只是一些可能使代码干净的想法呃,

  • SomePanel
    类中,将遍历代码放入构造函数外的方法中。构造函数用于初始化字段
  • 首先启动静态GUI,然后生成一个工作线程,通过前面的方法进行更新(这将是您的小型“引擎”)。在此线程中,您可以调用
    sleep
  • traverseverticserecoursive
    方法中,仅在UI线程上重新绘制,并在工作线程上更新状态

  • 您应该做的主要修改是,不要像他们在第一个答案中告诉您的那样,用睡眠调用阻止GUI线程。

    只是一些可能使代码更干净的想法:

  • SomePanel
    类中,将遍历代码放入构造函数外的方法中。构造函数用于初始化字段
  • 首先启动静态GUI,然后生成一个工作线程,通过前面的方法进行更新(这将是您的小型“引擎”)。在此线程中,您可以调用
    sleep
  • traverseverticserecoursive
    方法中,仅在UI线程上重新绘制,并在工作线程上更新状态

  • 您应该做的主要修改是,不要像他们在第一个答案中告诉您的那样,用睡眠调用阻止GUI线程。

    线程。睡眠是一个长时间运行的任务。当您在EDT中运行这样一个任务时,它会阻止所有重绘请求的执行。所有挂起的重绘请求以及在e睡眠阶段排队等待将来处理

    因此,当EDT退出
    睡眠
    阶段时,它会合并所有此类重新绘制请求(如果启用了合并,这是默认属性)如果未启用合并,则所有排队请求都将连续执行,其间没有任何时间间隔。因此,UI似乎没有更新


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

    线程。睡眠是一项长时间运行的任务。当您在EDT中运行这样的任务时,它会阻止所有重新绘制请求的执行。所有挂起且在睡眠阶段发送的重新绘制请求都会被禁用e排队等待将来处理

    因此,当EDT退出
    睡眠
    阶段时,它会合并所有此类重新绘制请求(如果启用了合并,这是默认属性)如果未启用合并,则所有排队请求都将连续执行,其间没有任何时间间隔。因此,UI似乎没有更新


    要纠正这种情况,请使用一个在特定时间间隔后定期触发的计时器。

    Guy,您可以使用一个与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);
        }
    }
    
    void play(){
    线程线程=新线程(){
    @凌驾
    公开募捐{
    游戏();
    }
    };
    thread.start();
    }
    无效游戏(){
    对于(;;){
    开关(状态){
    case GameData.ANIMATING:
    //将某些函数调用为repaint()以更新GUI
    打破
    案例GameData.GAME_结束:
    返回;
    违约:
    打破
    }
    diffTime=System.currentTimeMillis()-beforeTime;
    睡眠时间=延迟-扩散时间;
    睡眠时间=(睡眠时间<0)?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);
        }
    }
    
    void play(){
    线程线程=新线程(){
    @凌驾
    公开募捐{
    游戏();
    }
    };
    thread.start();
    }
    无效的