2012-01-09 73 views
1

我试图做的很简单,我想显示在屏幕上算法的步骤,因此为什么即时尝试将repaint()与睡眠(),但我做错了,我喜欢它,如果有人足够了解它,先解释这个代码有什么问题,其次,我该怎么办才能使它工作...结合repaint()和Thread.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

不要在事件指派线程不能入睡;这会导致GUI冻结。对于动画,请使用EDT友好的实用工具类,例如javax.swing.Timer

+0

你能告诉我它是如何完成的吗?把我写的代码,并把它的变化... – 2012-01-09 16:50:42

+1

@OfekRon,看到[这](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html)。 – mre 2012-01-09 16:52:37

+0

@OfekRon很多人不会把完整的代码。但对于那些愿意的人来说,一些好的鼓励就是添加你自己的代码的[SSCCE](http://sscce.org/),而不仅仅是代码片段。 – 2012-01-09 17:00:18

1

只是一些想法,可能使你的代码更加清晰:

  1. 在你SomePanel类,把穿越代码的方法进行构造的。构造函数用于初始化字段。
  2. 首先启动你的静态GUI,然后产生一个工作线程通过前面的方法做更新(这将是你的小型“引擎”)。在这个线程是你可以打电话sleep
  3. 在您的traverseVerticesRecoursive方法中,只对UI线程重新绘制,并在工作线程上进行状态更新。

你应该做的主要修改是不阻止带睡眠呼叫的GUI线程,就像他们在第一个答案中告诉你的那样。

+0

这是一个很好的答案,但我需要那么一个更律位信息,specificly部分答案的3需要更多的解释,个例将大大appriciated,谢谢! – 2012-01-09 18:10:24

+0

BTW,即时通讯意识到它不是传统的投入在建筑工的函数调用,但那只是针对为例,没有想使之更加复杂那么它是... – 2012-01-09 18:13:12

+0

我试图说明的是,你通常希望首先实例化一个对象(在这里您只希望创建对象),然后调用该实例上的一个方法,以启动一个进程。一个例子就是'Thread'类。首先,你做'线程t =新的Thread();',然后调用't.start();' – 2012-01-11 09:34:52

0

Thread.sleep是一个长期运行的任务。当您在EDT中运行这样的任务时,它会阻止执行的所有重新绘制请求。所有正在挂起并在睡眠阶段发送的重新绘制请求都会排队等待未来处理。

因此,当EDT走出sleep阶段时,它会将所有重新绘制请求(如果已启用默认属性启用了合并)合并为一个执行的重新绘制。如果未启用合并,则所有排队的请求都会连续执行,而两者之间没有任何时间间隔。因此,UI似乎没有更新。

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

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); 
    } 
}