1. 程式人生 > >java中元件的paint(Graphics g)與paintComponent(Graphics g)的區別

java中元件的paint(Graphics g)與paintComponent(Graphics g)的區別

/---------------資料1---------------/

昨晚小許同學把paintComponent方法以一t之差寫成painComponent,在花費了大量的人力物力之後
才找到這個錯誤,不得不感慨:粗心才是程式設計師的噩夢啊!Swing之paint與paintComponent的區別 馬士兵曰過:“重寫方法你給我在API文件中找方法簽名!”,小許,你懂了嗎? 不過小許問的問題倒讓我發現了Swing中paint與paintComponent的區別。 查API文件,查得在類Jcomponent下的paint方法有以下解釋:       “This method actually delegates the work ofpainting to three protected            methods: 
paintComponentpaintBorder,and paintChildren.They're called in the           order listed to ensure that children appear ontop of component itself.” 也就是說當Swing中的paint方法被呼叫時,paintComponent、paintBorder、       paintChildren這三個方法也會被按順序呼叫,之所以要按這個順序呼叫是為了保證子元件能正確地顯示在目前這個元件之上。 所以paintComponent就是本身這個容器自己畫出自己元件的方法了。如果只是為了改變本身這個容器中的元件,只需要改寫
paintComponent方法就可以了,如果還要保留容器中的原本元件就別忘了呼叫super.paintComponent(g)。如果要改寫paint方法來改變本身這個容器的元件,那麼也別忘了要呼叫super.paint(g),不然出來的東西是不包含原元件、原邊框和子元件的。這個做個實驗就可以很快驗證的。 public class MyDrawPanelextends JPanel{ public void paint(Graphics g){ super.paint(g); g.setColor(Color.orange); g.fillRect(20, 50, 100, 100); } public static void main(String[] args){ JFrame frame = new JFrame(); MyDrawPanel panel = new MyDrawPanel(); JLabel label = new JLabel("aaa"); panel.setBackground(Color.blue); panel.add(label); frame.getContentPane().add(panel); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 300); frame.setVisible(true); } } 以上這個程式除了JPanel本身正常顯示之外還會顯示出子元件label和一個方塊。如果註釋掉super.paint(g),那麼就只能顯示出方塊了。 不過我還發現了一個更神奇的地方。
那就是以上這些只適用於Swing,如果換成awt就不同了。 awt要改變元件樣式,只能重寫paint方法了,因為他是沒有paintComponent方法的。什麼?你有發現這個方法?!如果你看清楚你就會發現這個方法不是paintComponent而是paintComponents方法,後面多了一個sSwing之paint與paintComponent的區別 這個paintComponents方法按API說是用來把所有的容器內元件都顯示出來的方法,我做了一下實驗,這個方法在容器物件初始化的時候應該是沒有被自動呼叫的,當你要用的時候只能自己呼叫了,不過好像只是顯示出子元件而已,因為awt中即使重寫paint方法而沒有呼叫父類的paint方法是不影響本身容器自己的元件顯示的。這是一個例子: public class MyDrawPanelextends Panel{ public void paint(Graphics g){ //super.paint(g); g.setColor(Color.orange); g.fillRect(20, 50, 100, 100); paintComponents(g); } public static void main(String[] args){ JFrame frame = new JFrame(); MyDrawPanel panel = new MyDrawPanel(); JLabel label = new JLabel("aaa"); panel.setBackground(Color.blue); panel.add(label); frame.getContentPane().add(panel); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 300); frame.setVisible(true); } }     可以把paintComponents(g)註釋掉再看看效果。 總結了一下:Swing中改變元件樣式重寫paintComponent就可以了,其他paintBorder和paintChildren預設就可以。awt中改變元件樣式要重寫paint方法,而且如果不需要呼叫super.paint(g)就可以保留原元件樣式,但是不會顯示子元件樣式,可以呼叫paintComponents(g)解決這個問題。

/---------------------資料2-----------------------/

AWT 和 Swing 中元件的繪製方式不同,繪製方法的實現也有區別。

AWT 中元件重繪時先呼叫 update(Graphics g) 清除以前繪製的,再呼叫 paint() 方法裡進行繪製,所以在 AWT 元件裡重繪時,只要簡單的覆寫 paint() 方法就可以了。

而在Swing 中,元件繪製 paint() 方法會依次呼叫 paintComponent(),paintBorder(),paintChildren() 三個方法。根據方法名就可以看出,paintComponent() 繪製元件本身,paintBorder() 繪製元件的邊框,paintChildren() 繪製元件的子元件,所以Swing 程式設計時,如果繼承 JComponent 或者其子類需要重繪的話,只要覆寫 paintComponent() 而不是 paint(),方法 paintBorder(),paintChildren() 一般預設即可