2012-09-25 73 views
3

我有一個Frame這是一種顏色,但在角落裏有一些文字。我設置顏色,實際上是從顯示器讀取顏色,然後根據這些測量值進行一些計算。等待AWT重繪完成

問題是,打電話repaint()導致Frame被繪我做的測量。我假設這是由於repaint()委託給EDT,但由於在實際噴漆工作之前/期間進行的測量,我得到的結果不正確。

我最初的想法是把一個聽衆放在油漆完成上,但我重新刷新更頻繁地比文本更新顏色,我不想聽這些事件。在進行測量之前,我如何等待實際的繪畫任務完成?

+0

您可以同步圍繞匿名鎖對象的線程以使一個線程等待另一個線程。 – Vulcan

+0

我的頭頂,我認爲你不能(可靠地)。您可以嘗試使用'SwingUtilities.invokeLater(Runnable)'在調用重繪後將您的計算放到EDT的尾部,但不能保證在EDT上已經放置了重繪請求... – MadProgrammer

+0

@Vulcan但我無法控制美國東部時間,是嗎?我認爲從實際的角度來看,美聯儲可能是先進先出法,但從正確的角度來看,我確信這一點? –

回答

0

令人讚歎,你可以找到...現在

EventQueue.invokeLater(new Runnable() { 
    @Override 
    public void run() { 

     Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { 
      @Override 
      public void eventDispatched(AWTEvent event) { 

       PaintEvent pe = (PaintEvent) event; 

       String type = ""; 
       if (pe.getID() == PaintEvent.PAINT) { 
        type = "PAINT"; 
       } else if (pe.getID() == PaintEvent.PAINT_FIRST) { 
        type = "PAINT_FIRST"; 
       } else if (pe.getID() == PaintEvent.PAINT_LAST) { 
        type = "PAINT_LAST"; 
       } else if (pe.getID() == PaintEvent.UPDATE) { 
        type = "UPDATE"; 
       } 

       System.out.println(type + "; pe.UpdateRec = " + pe.getUpdateRect() + "; pe.component = " + pe.getComponent()); 

      } 
     }, AWTEvent.PAINT_EVENT_MASK); 

     JFrame frame = new JFrame("Testing"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(200, 200); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 


    } 
}); 

,因爲重繪請求可以來思考和快速,我會忍不住放置在一個小的「延遲」將在最後不久解僱請求已完成......

private Timer updateTimer; 

// ... 

EventQueue.invokeLater(new Runnable() { 
    @Override 
    public void run() { 

     updateTimer = new Timer(250, new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       // Update compulations here... 
      } 
     }); 
     updateTimer.setRepeats(false); 
     updateTimer.setCoalesce(true); 

     Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { 

      @Override 
      public void eventDispatched(AWTEvent event) { 
       updateTimer.restart(); 
      } 
     }, AWTEvent.PAINT_EVENT_MASK); 
    } 
} 

的想法是,讓最後的重畫請求和你的編譯的開始之間至少250毫秒。你可能會喜歡擺弄這些值了一下,看看有什麼適合你...

UPDATE

您也可以嘗試在此組件及所有JComponent.paintImmediately

繪製指定的區域其立即與該地區重疊的 後代。

很少有必要調用此方法。在大多數情況下,更高效地調用重繪,這會延遲實際繪畫,並且可以將冗餘請求摺疊爲單個繪畫調用。如果在調度當前事件 時需要更新顯示器,此方法爲 。

+0

我明白你想要做什麼在這裏 - 但你確定他們會按照正確的順序放入EDT嗎?一些測試顯示調用'repaint()'曾經對我的'paint()'方法產生了5次調用,我不知道這些調用是同步的還是添加到事件隊列的末尾。 –

+0

因爲可以重新整理請求,所以不能保證它們會按照您請求的順序顯示。 – MadProgrammer

+2

我不確定您的解決方案如何實際工作。它似乎圍繞着「延遲代碼並希望最好」展開。我錯了嗎? –