20110917

為何在swing事件處理中 repaint 無法被調用?

   1. public void actionPerformed( ActionEvent e ){  
   2.    
   3.       panel.repaint();  
   4.    
   5.       for( int i = 0; i < 200; i++){  
   6.    
   7.         x += 50;  
   8.         y += 50;  
   9.    
  10.         panel.repaint();  //無法被調用
  11.    
  12.         try{  
  13.    
  14.           Thread.currentThread().sleep( 50 );  
  15.    
  16.         }// close try  
  17.         catch( Exception ex ){  
  18.         }// close catch  
  19.    
  20.       }//close for  
  21.    
  22.     }//close actionPerformed      

Why does it works outside the actionPerformed and doesn't inside??
The event dispatch thread does one thing at a time.
Try starting the animation on another thread.
請開新Thread處理重繪。
因為"事件處理" 與 "重繪"都會使用EDT去完成。
每次發生"事件處理" 與 "重繪處裡"時,會將事件與重繪(兩者都是非同步處理,會立即返回!)排列到EDT的Queue當中等待EDT照順序處裡。
試想,當"事件處理"非常耗時冗長(例如長時間的迴圈或是遠端資料讀取),且"事件處理"包含著repaint請求(也就是"重繪處理"),會使GUI失去回應,且不斷的堆疊repaint在EDT的queue裡,因為EDT還在處理那段冗長的事件!根本沒空處理重繪,所以GUI整個失效。

   1. public void actionPerformed( ActionEvent e ){  
   2.     // if we are not now animating  
   3.     animate();  
   4. }  
   5.    
   6. private void animate() {  
   7.     Thread thread = new Thread(new Runnable() {  
   8.         public void run() {  
   9.             for( int i = 0; i < 200; i++){  
  10.                 x += 50;  
  11.                 y += 50;  
  12.                 panel.repaint();  
  13.             try{  
  14.                 Thread.currentThread().sleep( 50 );  
  15.             } catch( Exception ex ){  
  16.                 break;  
  17.             }  
  18.         }  
  19.     }  
  20.     thread.setPriority(Thread.NORM_PRIORITY);  
  21.     thread.start();  
  22. }  
swing 執行緒簡介
更多有關EDT

20110902

getGraphics() 回傳 NULL

要在APPLET(init階段)裡取得Jpanel的graphics時遇到return null的問題,google後發現似乎並不能隨時取得container裡componen的graphic,至少在container為不可見時後,container裡的componet都無法取得graphics,但有別的方法可以在不可見或初始階段就先寫好繪圖。
(但其實仍是在容器可見時才執行)
//失敗(JApplet init) jp.getGraphics() 為null
JPanel jp=new JPanel();
jp.getGraphics().drawString("123",20,20);

//可取得
JPanel jp=new JPanel(){
    public void paintComponent(Graphics  g){
        g.drawString("21113", 10, 200);
    }
};

//在事件中也可取得
button.addMouseListener(new   MouseAdapter(){
   public   void   mouseClicked(MouseEvent me){
      Graphics2D g2 =(Graphics2D) panel.getGraphics();
      g2.drawRect(20,20,100,300);
   }
});