2012-01-09 65 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); 
    } 
}