2014-03-25 55 views
0

這是由布氏算法計算出的位置畫點的代碼:延遲不是在Java圖形工作

public void drawBresenhamPoints(Graphics2D g2, List<Point> bresenham) throws InterruptedException 
{ 
     Graphics2D g = (Graphics2D) g2; 

    if(bresenham == null) 
     return; 

    g.setColor(Color.DARK_GRAY); 

    for(int i = 0; i < bresenham.size(); i = i+20) 
    { 
     int x = bresenham.get(i).x - pointWidth1/2; 
     int y = bresenham.get(i).y - pointWidth1/2; 

     int ovalW = pointWidth1; 
     int ovalH = pointWidth1; 

     g.fillOval(x, y, ovalW, ovalH); 

      // delay 
     try 
     { 
      Thread.sleep(10); 
     } 
     catch(Throwable e) 
     { 
     System.out.println(e.getMessage()); 
     } 
    } 
} 

名單「布氏」包含了一切與布氏的幫助下預先計算的點畫線算法。我想在'for'循環中設置1秒的延遲,以便在1秒的時間間隔後繪製每個點。 「延遲」部分中列出的部分不起作用。如何使延遲工作? 更具體地說,我想要在屏幕上以1秒爲間隔逐個繪製所有點。

+0

閱讀有關定時器和不使用的睡眠,避免鎖EDT感謝 – StanislavL

回答

4

我假設你在paint/paintComponent方法中調用此方法。

只是一個指針:永遠不睡覺的烤漆工藝

而是使用一個javax.swing.Timer重複任務。什麼會做的是

  • 有兩臺Lists。您的List<Point> bresenham和另一個List<Point> paintListbresenham將保存您的數據,並且paintList將最初爲空。

  • 使用paintList作畫貴點

    @override 
    protected void paintComponent(Graphics g) { 
        super.paintComponent(g); 
        Graphics2D g2 = (Graphics2D)g; 
    
        for (Point p : paintList) { 
         int x = bresenham.get(i).x - pointWidth1/2; 
         int y = bresenham.get(i).y - pointWidth1/2; 
    
         int ovalW = pointWidth1; 
         int ovalH = pointWidth1; 
    
         g.fillOval(x, y, ovalW, ovalH); 
        } 
    } 
    
  • 雖然沒有什麼最初在paintList是,您將添加一個新的Point到列表中的定時器事件的每一個射擊。

    Timer timer = new Timer(100, new ActionListener(){ 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         if (bresenham.isEmpty()) { 
          ((Timer)e.getSource()).stop(); 
         } else { 
          paintList.add(bresemham.get(0)); 
          bresenham.remove(0); 
         } 
         repaint(); 
        } 
    }); 
    timer.start(); 
    

    構造的基本計時器是杉杉的delay,這是「迭代」,並在實際監聽爲每delay毫秒觸發的計時器事件偵聽器的第二個參數之間的延遲時間。那麼上面的代碼基本上做的是將Point添加到從bresenham列表中取出的paintList,然後刪除項目repaint,其調用paintComponent。當列表爲空時,計時器將停止。


UPDATE

這裏有一個完整的運行例子

import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Point; 
import java.awt.event.*; 
import java.util.*; 
import javax.swing.*; 
import javax.swing.Timer; 

public class BresenhamPoints extends JPanel { 

    private static final int D_W = 500; 
    private static final int D_H = 500; 

    private List<Point> bresenhamList; 
    private List<Point> paintList; 

    public BresenhamPoints() { 
     bresenhamList = createRandomPoints(); 
     paintList = new ArrayList<>(); 

     Timer timer = new Timer(100, new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       if (bresenhamList.isEmpty()) { 
        ((Timer) e.getSource()).stop(); 
       } else { 
        paintList.add(bresenhamList.get(0)); 
        bresenhamList.remove(0); 
       } 
       repaint(); 
      } 
     }); 
     timer.start(); 
    } 

    private List<Point> createRandomPoints() { 
     Random rand = new Random(); 
     List<Point> list = new ArrayList<>(); 
     for (int i = 0; i < 100; i++) { 
      list.add(new Point(rand.nextInt(D_H), rand.nextInt(D_H))); 
     } 
     return list; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     for (Point p : paintList) { 
      g.fillOval(p.x - 5, p.y - 5, 10, 10); 
     } 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(D_W, D_H); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JFrame frame = new JFrame(); 
       frame.add(new BresenhamPoints()); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 
+0

很多。你的解決方案很好。 –

0

sleep方法的值爲毫秒,所以你睡了10ms。將其更改爲1000會產生更明顯的中斷。

正如指出的那樣,您不應該在EDT上有任何時間消耗甚至更糟的鎖定機制,因爲它會掛起整個應用程序。您可以使用Timer來觸發事件並一次畫出一個點。 This以前的SO帖子應該做你需要的。